[HAOI2018]苹果树(组合数学)

首先有个很奇妙而且很有用的性质:每个二叉树对应唯一的中序遍历,然后每个二叉树出现概率相同。所以n个节点的二叉树形态是n!种(题目中说了*n!已经是提示了),对每种方案求和即可得到期望。令f[i]表示i个节点的子树,根深度为1时,所有点的期望深度之和乘i!的值,令g[i]表示i个节点的子树,期望两两路径之和乘i!的值。

然后得到f[i]=i*i!+ΣC(i-1,L)(f[L]*R!+f[R]*L!),g[i]=ΣC(i-1,L)(g[L]*R!+g[R]*L!+f[L]*R!*(R+1)+f[R]*L!*(L+1)),其中0<=L<i,L、R为左/右子树大小,只需要枚举L即可(因为R=i-1-L),复杂度O(n2)

这题这么水的吗qwq?其实当模数做NTT时,貌似可以分治NTT优化O(nlog2n),反正我不会就不管了。

#include<bits/stdc++.h>
using namespace std;
const int N=2019;
int n,mod,c[N][N],fac[N],f[N],g[N];
int main()
{
    scanf("%d%d",&n,&mod);
    fac[0]=c[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        c[i][0]=1,fac[i]=1ll*fac[i-1]*i%mod;
        for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
    }
    f[1]=1;
    for(int i=2;i<=n;i++)
    {
        for(int L=0;L<i;L++)
        {
            int R=i-1-L,F,G;
            F=(1ll*f[L]*fac[R]+1ll*f[R]*fac[L])%mod;
            G=(1ll*f[L]*fac[R]%mod*(R+1)+1ll*f[R]*fac[L]%mod*(L+1)+1ll*g[L]*fac[R]+1ll*g[R]*fac[L])%mod;
            f[i]=(f[i]+1ll*F*c[i-1][L])%mod;
            g[i]=(g[i]+1ll*G*c[i-1][L])%mod;
        }
        f[i]=(f[i]+1ll*i*fac[i])%mod;
    }
    printf("%d",g[n]);
}
View Code

猜你喜欢

转载自www.cnblogs.com/hfctf0210/p/10919962.html