[CSP-S模拟测试]:Seat(概率DP+数学)

题目描述

有$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++

原文地址:https://www.cnblogs.com/wzc521/p/11624841.html

时间: 2024-08-30 12:58:53

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

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

题意:给定三个表达式,问你求出最小的m1,m2,满足G(m1) >= F(n), G(m2) >= G(n). 析:这个题是一个概率DP,但是并没有那么简单,运算过程很麻烦. 先分析F(n),这个用DP来推公式,d[i],表示抛 i 次连续的点数还要抛多少次才能完成.那么状态转移方程就是 d[i] = 1/6*(1+d[i+1]) + 5/6*(1+d[1]), 意思就是说在第 i 次抛和上次相同的概率是1/6,然后加上上次抛的和这一次,再加上和上次不同的,并且又得从第1次开始计算. 边界就是

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

题目传送门(内部题57) 输入格式 第一行包含一个数:$n$表示树的节点数.接下来$n-1$行,每行包含两个数:$u,v$表示无根树的一条边. 输出格式 输出$n$行,第$i$行包含一个浮点数,保留三位小数,表示第$i$号点第一次访问的期望时间. 样例 样例输入: 31 22 3 样例输出: 1.0002.0005.000 数据范围与提示 样例解释: 样例解释:容易分析出,所有可能情况下,到达$1$号点和$2$号点的时间都分别是:$1$和$2$,我们考虑$3$号点的到达时间,所有可能的过程:$1

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

题目描述 由于出题人赶时间所以没办法编故事来作为背景.一开始有$n$个苹果,$m$个人依次来吃苹果,第$i$个人会尝试吃$u_i$或$v_i$号苹果,具体来说分三种情况.$\bullet 1.$两个苹果都还在,那么这个人将随便选一个苹果吃了.$\bullet 2.$只有一个苹果,那么这个人将吃掉这个苹果.$\bullet 3.$都不在了,这个人吃不到苹果就走了.请问有多少对苹果$(i,j)(i<j)$满足它们两个都幸存下来的概率$>0$. 输入格式 第一行两个数$n,m$.接下来$m$行,每行

[poj2096] Collecting Bugs【概率dp 数学期望】

传送门:http://poj.org/problem?id=2096 题面很长,大意就是说,有n种bug,s种系统,每一个bug只能属于n中bug中的一种,也只能属于s种系统中的一种.一天能找一个bug,问找到的bug涵盖所有种类的bug与所有种类的系统期望需要几天. 令f(i, j)为找到了i种bug,j种系统期望的天数,那么今天再找一个bug,有4种情况: ①,bug种类为已找到的i种中的一种,系统种类为已找到的j种中的一种,则概率p1 = (i / n) * (j / s) ②,bug种类

[CSP-S模拟测试]:折射(DP)

题目描述 小$Y$十分喜爱光学相关的问题,一天他正在研究折射. 他在平面上放置了$n$个折射装置,希望利用这些装置画出美丽的折线. 折线将从某个装置出发,并且在经过一处装置时可以转向,若经过的装置坐标依次为$(x_1,y_1),(x_2,y_2),...(x_k,y_k)$,则必须满足: $\bullet \forall j\in (1,k],y_j<y_{j−1}$ $\bullet \forall j\in (2,k],x_{j−2}<x_j<x_{j−1}or\ x_{j−1}&l

[CSP-S模拟测试]:花(DP)

题目传送门(内部题111) 输入格式 一个整数$T$,表示测试数据组数. 每组测试数据占一行,两个整数,分别表示$L$和$S$. 输出格式 对每组数据,输出一个整数表示答案. 样例 样例输入1: 13 7 样例输出1: 7 样例输入2: 24 210 11 样例输出2: 4410199993 数据范围与提示 样例$1$解释: 一共有$7$种形态,每种形态能构成$1$个方案. 样例$2$解释: AAAB ABBB BAAA BBBA 数据范围: 对于$60\%$的数据,$L\leqslant 30

[CSP-S模拟测试]:蛇(DP+构造+哈希)

题目传送门(内部题140) 输入格式 前两行有两个长度相同的字符串,描述林先森花园上的字母. 第三行一个字符串$S$. 输出格式 输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模. 样例 样例输入1: rwbyybwrrwby 样例输出1: 4 样例输入2: oooooooo 样例输出2: 14 数据范围与提示 对于$20\%$的数据,$n,|S|\leqslant 16$. 对于$40\%$的数据,$n,|S|\leqslant 40$. 对于$60\%$的数据,$n,|S|\l

[hdu4035] Maze【概率dp 数学期望】

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4035 真的是一道好题,题解比较麻烦,我自己在纸上写了好大一块草稿才搞出来,不用公式编辑器的话就很难看清楚,所以不上题解啦,贴一个题解的链接:http://blog.csdn.net/balloons2012/article/details/7891054 注意此题卡精度,我一开始eps是1e-8,WA掉了,开到了1e-10,AC~,真是烦卡精度的题. #include <cstdio> #inclu

[CSP-S模拟测试]:画作(BFS+数学)

题目描述 小$G$的喜欢作画,尤其喜欢仅使用黑白两色作画.画作可以抽象成一个$r\times c$大小的$01$矩阵.现在小$G$构思好了了他的画作,准备动笔开始作画.初始时画布是全白的,他每一次下笔可以将一个四联通的部分涂成黑色或白色.你需要告诉他,在给出的构思下,他最少需要下笔多少次才能完成画作. 输入格式 第一行两个正整数$r,c$.接下来$r$行,每行$c$个字符,表示目标画作. 输出格式 输出一行一个正整数,表示最少需要的下笔步数. 样例 样例输入: 3 3010101010 样例输出