【2019/02/18测试T2】玩具

【题目】

传送门

题目描述:

这个故事发生在很久以前,在 IcePrincess_1968IcePrince_1968 都还在上幼儿园的时候。

IcePrince_1968 最近迷上了一种玩具,这种玩具中有两种零件:圆球和棍子。棍子的两头可以插在两个圆球上的各一个空洞中,从而将两个圆球连接起来。为了保证玩具的娱乐性,任意一个圆球上的空洞个数总是多于玩具套装中的棍子数。你可以认为圆球是没有体积的,所有棍子的长度均为 1 1

IcePrince_1968 喜欢这样玩这种玩具:他先摸出玩具袋里的一个圆球放在地上,然后重复下面的操作 n 1 n-1 次:每次从袋中取出一个圆球和一根棍子,然后等概率的从地上的圆球中选择一个,将该圆球和选择的圆球用棍子连起来,使得新的圆球在选中圆球的正上方。

IcePrince_1968 对自己搭出的艺术品很满意,便决定把这个物品送给 IcePrincess_1968 作为生日礼物。然而生日礼物是需要包装的,因为默认圆球没有体积,所以 IcePrince_1968 不用考虑包装盒的长和宽,但是包装盒的高是需要确定的,这里我们假设 IcePrince_1968 是一个非常节俭的孩子,所以包装盒的高总是等于艺术品的高度。IcePrince_1968 想知道自己需要的包装盒的高的期望对质数 p p 取模后的值,但他还在上幼儿园,怎么会算呢,于是就请你来帮助他。

输入格式:

输入数据仅一行,包含两个正整数 n , p n,p ,表示最终的艺术品中圆球的个数和模数 p p

输出格式:

输入文件仅一行,一个正整数,表示包装盒的高的期望对质数 p p 取模后的值。

样例数据:

输入
3 998244353

输出
499122178

提示:

【输入输出样例 1 1 解释】

三个圆球组成的艺术品,高度只可能是 1 1 或者 2 2 ,所以高度的期望是 1.5 1.5 ,在模 998244353 998244353 下的期望是 499122178 499122178

【数据范围】

对于 30 % 30\% 的数据,满足 n 10 n\le 10 p 1 , 000 , 007 p\le1,000,007

对于 50 % 50\% 的数据,满足 n 20 n\le20

对于 70 % 70\% 的数据,满足 n 50 n\le50

对于 100 % 100\% 的数据,满足 n 200 n\le200 p 1 , 000 , 000 , 007 p\le1,000,000,007 p p 是质数。


【分析】

这道题我不是很会,先放上题解吧。

显然我们可以把最后做出来的玩具当成一棵树。

定义 f i , j f_{i,j} 为有 i i 个点的树,深度不超过 j j 层的概率, g i , j g_{i,j} 为有 i i 个点的森林,深度不超过 j j 层的概率。

还有一个要预处理的:设 d p i , j dp_{i,j} 表示对于有 i i 个点的森林,有 j j 个点在第一个子树内的概率。

那么预处理的转移方程就是:

d p i , j = d p i 1 , j 1 × ( j 1 ) × i n v ( i ) + d p i 1 , j × ( i j ) × i n v ( i ) dp_{i,j}=dp_{i-1,j-1}\times (j-1)\times inv(i) + dp_{i-1,j}\times (i-j)\times inv(i)

然后又因为 f i , j f_{i,j} 可以从 g i 1 , j 1 g_{i-1,j-1} 直接转移过来,就是:

g i , j = k = 1 i f k , j × g i k , j × d p i , k g_{i,j}= \sum_{k=1}^{i} f_{k,j} \times g_{i-k,j} \times dp_{i,k}

最后的答案就是 i = 1 n 1 ( f n , i f n 1 , i ) \sum\limits_{i=1}^{n-1} (f_{n,i}-f_{n-1,i})


【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 205
using namespace std;
int n,p;
int dp[N][N],f[N][N],g[N][N],inv[N];
signed main()
{
	int i,j,k,ans=0;
	scanf("%d%d",&n,&p);
	inv[0]=inv[1]=1,dp[1][1]=1;
	for(i=2;i<=n;++i)  inv[i]=1ll*(p-p/i)*inv[p%i]%p;
	for(i=2;i<=n;++i)
	  for(j=1;j<=n;++j)
	    dp[i][j]=(1ll*dp[i-1][j-1]*(j-1)%p*inv[i]%p+1ll*dp[i-1][j]*(i-j)%p*inv[i]%p)%p;
	for(i=0;i<=n;++i)  g[0][i]=1;
	for(i=1;i<=n;++i)
	{
		for(j=0;j<=n;++j)
		{
			if(j)  f[i][j]=g[i-1][j-1];
			else  if(i==1)  f[i][j]=1;
			for(k=1;k<=i;++k)
			  g[i][j]=(g[i][j]+1ll*f[k][j]*g[i-k][j]%p*dp[i][k]%p)%p;
		}
	}
	for(i=1;i<=n;++i)
	  ans=(ans+1ll*(f[n][i]-f[n][i-1]+p)%p*i%p)%p;
	printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/87686372
T2