长沙雅礼集训题 树
概率期望? NO 计数DP
考场上看到期望后直接弃掉打了暴力。
期望根本没法转移,数据也不大,所以这个题就是在计数。
一个很妙的思想,最大深度要不是挂在2上,要不不是挂在2上。
所以分类计数后DP就很明显了。
因为以二为根的树的状态可以用之前递推出来的以一为根的树的状态。
换句话说,n个点i深度的树的方案数是一定的,树的形态不变,只是需要在i-2个点中
(去掉1和2所以减去2)任取k-1个作为二的子树节点。
这可以用杨辉三角递推组合数解决。
此题完美解决。。。。
code
include<bits/stdc++.h>
using namespace std;
#define int long long
double cc[25][25],dp[25][25],ans;
int c[25][25],f[25][25],aaa;
int n,mod;
inline int qpow(int a,int b)
{ int base=1;
while(b)
{ if(b&1)base=(base*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return base;
}
signed main()
{
scanf("%lld%lld",&n,&mod);
for(int i=0;i<=n;++i)
{ cc[i][0]=1;
c[i][0]=1;
for(int j=1;j<=i;++j)
{ cc[i][j]=cc[i-1][j-1]+cc[i-1][j];
c[i][j]=(c[i][j]+c[i-1][j-1]+c[i-1][j])%mod;
}
}
dp[1][1]=dp[2][2]=1;f[1][1]=f[2][2]=1;
for(int i=3;i<=n;++i)
for(int j=2;j<=i;++j)
{ for(int k=1;k<=i-2;++k)
for(int l=1;l<=min(j-2,k);++l)
{ f[i][j]=(f[i][j]+f[k][l]*f[i-k][j]%mod*c[i-2][k-1]%mod)%mod;
dp[i][j]+=dp[k][l]*dp[i-k][j]*cc[i-2][k-1];
}
for(int k=1;k<i;++k)
for(int l=1;l<=j;++l)
{ f[i][j]=(f[i][j]+f[k][j-1]*f[i-k][l]%mod*c[i-2][k-1]%mod)%mod;
dp[i][j]+=dp[k][j-1]*dp[i-k][l]*cc[i-2][k-1];
}
}
for(int i=1;i<=n;++i)
{ ans+=dp[n][i]*i;
aaa=(aaa+f[n][i]*i)%mod;
}
double jc=1;int jc1=1;
for(int i=1;i<n;++i)jc*=i,jc1=(jc1*i)%mod;
printf("%.0lf\n",round(ans/jc));
printf("%lld",(aaa*qpow(jc1,mod-2))%mod);
}