题目描述

有$n+2$个座位等距地排成一排,从左到右编号为$0$至$n+1$。
最开始时$0$号以及$n+1$号座位上已经坐了一个小$G$,接下来会有$n$个小$G$依次找一个空座位坐下。由于小$G$们坐得太近就容易互相搏弈,每个小$G$会找一个当前离最近的小$G$距离最远的座位坐下。如果有多个备选的座位,这个小$G$会等概率选择其中一个。
给出$n$,求第$i$个坐下的小$G$坐在$j$号座位的概率,对$P$取模。具体来说,如果答案化为最简分数可以表示为$\frac{a}{b}$,你需要输出$a\times b^{−1}$,其中$b^{−1}=b^{P-2}(\mod P)$。


输入格式

从文件$seat.in$中读入数据。
一行两个整数$n,P$。


输出格式

输出到文件$seat.out$中。
输出$n$个整数,第$i$行第$j$个整数表示第$i$个小$G$坐在第$j$个座位的概率。


样例

样例输入:

4 10007

样例输出:

0 5004 5004 0
3336 1668 1668 3336
3336 1668 1668 3336
3336 1668 1668 3336


数据范围与提示

样例解释:

第一个小$G$会在中间两个位置中随机选择一个,接下来无论选哪个位置最近的距离都是$1$。
$\frac{1}{2}=5004(\mod 10^4+7),\frac{1}{3}=3336(\mod 10^4+7),\frac{1}{6}=1668(\mod 10^4+7)$。

数据范围:

对于所有数据,满足$2\leqslant n\leqslant 1024,2000\leqslant P\leqslant 30000$,$P$是质数。
本题共$25$个测试点,每个测试点$4$分。


题解

好玄学的一道玄学题……

一个结论是,对于任意一个人,他坐下时离最近的人的距离是固定的,不随前面的人的决策而改变。这样我们可以将所有人按坐下时的距离分成若干层。另一个结论是,无论之前每一层如何决策,轮到这一层时逬空区间的长度构成的可重集也是固定的。
    对于最后一层特殊处理接下来均默认不是最后一层。对于之前的每一层,考虑在哪些空区间中央坐下可使得距离最大,其中可能会有一些长度为奇数的区间和一些长度为偶数的区间,而对于每个人来说,坐在任意一个奇数的区间的中央的概率都是相等的,偶数同理。
    那么我们只需要知道,每个人有多大的概率坐在一个奇逯偶数区间的中央。考虑$DP$,$dp[i][j]$表示这一层已经坐下$i$个人之后,还有$j$个长度为偶数的区间的概率,转移只需考虑当前这个人坐了哪类区间即可。遤遰之后容易算出之前要求的概率。
    区间长度为奇数时位置是固定的;考虑区间长度为偶数的情况,此时会出现两个位置可供选择,但无论选择哪一个,都会将区间划分成长度为$\frac{n}{2}$和$\frac{n}{2}−1$的两段。因此这两种选择具有对称性,我们只需要假定选择其中的一个,算出这种情况下之后的层的答案,即可对称地推出另一种情况下的答案。
    瓶颈在利用对称性推答案的地方,主要看代码实现了,反正我是颓的代码。

时间复杂度:$\Theta(n^2\log n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,P,now;
int dp[1100][1100],ans[1100][1100],g[1100][1100],inv[1100],vis[1100],cnt[1100],odd[1100],pos[1100];
int qpow(int x,int y)
{
int res=1;
while(y)
{
if(y&1)res=res*x%P;
x=x*x%P;
y>>=1;
}
return res;
}
void pre_work()
{
for(int i=1;i<=n;i++)inv[i]=qpow(i,P-2);
vis[0]=vis[n+1]=1;now=n;
}
int main()
{
scanf("%d%d",&n,&P);
pre_work();
for(int i=1;i<=n;i++)
{
pair<int,int> lr=make_pair(0,0);
for(int j=0;j<=n;j++)
{
int flag=j+1;
while(!vis[flag])flag++;
if(flag-j>lr.second-lr.first){lr=make_pair(j,flag);}
j=flag-1;
}
cnt[lr.second-lr.first>>1]++;
if((lr.second-lr.first)&1)odd[lr.second-lr.first>>1]++;
pos[i]=lr.first+(lr.second-lr.first>>1);
vis[lr.first+(lr.second-lr.first>>1)]++;
}
for(int i=1;i<=n;i++)
{
if(!cnt[i])continue;
if(i==1)
{
for(int j=now-cnt[i]+1;j<=now;j++)
for(int k=now-cnt[i]+1;k<=now;k++)
ans[j][pos[k]]=inv[cnt[i]];
}
else
{
for(int j=0;j<=cnt[i];j++)
for(int k=0;k<=odd[i];k++)
dp[j][k]=0;
dp[0][odd[i]]=1;
for(int j=1;j<=cnt[i];j++)
{
int oddw=0,even=0;
for(int k=0;k<=odd[i];k++)
{
if(!dp[j-1][k])continue;
int frac=(cnt[i]-(j-1))+k;
int w=0;
if(k)
{
w=dp[j-1][k]*k*2%P*inv[frac]%P;
even=(even+w*inv[odd[i]<<1])%P;
dp[j][k-1]=(dp[j][k-1]+w)%P;
}
if(cnt[i]-odd[i])
{
w=dp[j-1][k]*(frac-2*k)%P*inv[frac]%P;
oddw=(oddw+w*inv[cnt[i]-odd[i]])%P;
dp[j][k]=(dp[j][k]+w)%P;
}
}
for(int k=now-cnt[i]+1;k<=now-cnt[i]+odd[i];k++)
{
ans[now-cnt[i]+j][pos[k]]=(ans[now-cnt[i]+j][pos[k]]+even)%P;
ans[now-cnt[i]+j][pos[k]+1]=(ans[now-cnt[i]+j][pos[k]+1]+even)%P;
}
for(int k=now-cnt[i]+odd[i]+1;k<=now;k++)
ans[now-cnt[i]+j][pos[k]]=(ans[now-cnt[i]+j][pos[k]]+oddw)%P;
}
for(int j=now-cnt[i]+1;j<=now-cnt[i]+odd[i];j++)
{
int L=pos[j]-i+1;
int R=pos[j]+i;
for(int k=L;k<=R;k++)
{
if(k==pos[j])continue;
for(int l=now+1;l<=n;l++)
{
g[l][k]=(g[l][k]+ans[l][k]*inv[2])%P;
g[l][k<pos[j]?k+i+1:k-i]=(g[l][k<pos[j]?k+i+1:k-i]+ans[l][k]*inv[2])%P;
}
}
for(int k=L;k<=R;k++)
for(int l=now+1;l<=n;l++)
{
ans[l][k]=g[l][k];
g[l][k]=0;
}
}
}
now-=cnt[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",ans[i][j]);
puts("");
}
return 0;
}

rp++

[CSP-S模拟测试]:Seat(概率DP+数学)的更多相关文章

  1. [CSP-S模拟测试]:题(DP+数学)

    题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...

  2. [CSP-S模拟测试]:B(DP+数学)

    题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...

  3. HDU 4599 Dice (概率DP+数学+快速幂)

    题意:给定三个表达式,问你求出最小的m1,m2,满足G(m1) >= F(n), G(m2) >= G(n). 析:这个题是一个概率DP,但是并没有那么简单,运算过程很麻烦. 先分析F(n ...

  4. [CSP-S模拟测试]:大佬(kat)(数学期望)

    题目描述 辣鸡$ljh\ NOI$之后就退役了,然后就滚去学文化课了.他发现$katarina$大佬真是太强了,于是就学习了一下$katarina$大佬的做题方法.比如这是一本有$n$道题的练习册,$ ...

  5. CF 148D D. Bag of mice (概率DP||数学期望)

    The dragon and the princess are arguing about what to do on the New Year's Eve. The dragon suggests ...

  6. bzoj1415 [Noi2005]聪聪和可可【概率dp 数学期望】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1415 noip2016 D1T3,多么痛的领悟...看来要恶补一下与期望相关的东西了. 这是 ...

  7. [CSP-S模拟测试]:题(DP)

    题目描述 由于出题人赶时间所以没办法编故事来作为背景.一开始有$n$个苹果,$m$个人依次来吃苹果,第$i$个人会尝试吃$u_i$或$v_i$号苹果,具体来说分三种情况.$\bullet 1.$两个苹 ...

  8. [CSP-S模拟测试]:tree(DP)

    题目传送门(内部题57) 输入格式 第一行包含一个数:$n$表示树的节点数.接下来$n-1$行,每行包含两个数:$u,v$表示无根树的一条边. 输出格式 输出$n$行,第$i$行包含一个浮点数,保留三 ...

  9. 2018.10.17 NOIP模拟 发电机(概率dp)

    传送门 考试空间开大了爆零不然只有30分爆栈? 话说这题真的坑1e7没法写dfsdfsdfs 其实很好推式子. 考虑每个点安一个发动机的概率,推一波式子做个等比数列求和什么的可以证明出来是严格的1si ...

随机推荐

  1. python 操作openpyxl导出Excel 设置单元格格式以及合并处理

    贴上一个例子,里面设计很多用法,根据将相同日期的某些行合并处理. from openpyxl import Workbook from openpyxl.styles import Font, Fil ...

  2. mysql 函数 时间函数,数学函数,字符串函数,条件判断函数

    =========================================== mysql 相关函数 ============================================= ...

  3. CentOSLinux系统中Redis数据库的安装及配置

    MongoDB 传统方式安装 关闭 SELinux 编辑配置文件:vim /etc/selinux/config 把 SELINUX=enforcing 改为 SELINUX=disabled Mon ...

  4. Forbidden (CSRF token missing or incorrect.):错误解决办法

    在JS中,使用post方法提交数据到后台,出现错误: Forbidden (CSRF token missing or incorrect.):.........; 解决办法: 在页面导入JS的位置, ...

  5. 手写一个SpringMVC框架(转)

    一:梳理SpringMVC的设计思路 本文只实现自己的@Controller.@RequestMapping.@RequestParam注解起作用,其余SpringMVC功能读者可以尝试自己实现. 1 ...

  6. poj2019 二维RMQ裸题

    Cornfields Time Limit: 1000MS   Memory Limit: 30000K Total Submissions:8623   Accepted: 4100 Descrip ...

  7. Tomcat 8.5 apr 模式配置

    tomcat APR模式配置 一.环境 操作系统:Ubutnu 14 ubuntu@ubuntu:~$ uname -a Linux ubuntu 4.4.0-31-generic #50~14.04 ...

  8. vue 和react中子组件分别如何向父组件传值

    vue子组件和父组件双向传值: 子: Vue.component("childComponent",{ template:`<div><p @click='pos ...

  9. 如何在SVN服务器上创建项目

    1,首先你的电脑上安装了SVN的服务器 VisualSVN-Server-3.7.1-x64.msi 2,打开SVN服务器后,可以看到分布的目录是 Repositories.Users.Groups. ...

  10. linux系统升级openssh

    一.升级前准备工作 安装openssh过程需gcc,zlib-devel,openssl-devel,等编译环境,如果通过rpm包来安装,需要解决各种依赖包,故配置本地yum源解决依赖问题. 1. 配 ...