洛谷P3830 [SHOI2012]随机树——概率期望

题目:https://www.luogu.org/problemnew/show/P3830

询问1:f[x]表示有x个叶节点的树的叶节点平均深度;

    可以把被扩展的点的深度看做 f[x-1] ,于是两个新点深度为 f[x-1]+1,而剩下的x-2个点平均深度就是f[x-1];

    所以f[x] = [ f[x-1] * (x-2) + (f[x-1] + 1) * 2 ] / x ;

    整理得到f[x] = f[x-1] + 2 / x ;

询问2:f[i][j]表示有i个叶子节点、深度为j的概率;

    把状态分成两个子状态,就是左子树和右子树,转移即可;

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int q,n;
double f[105][105],ans;//[叶子个数][深度] <[左子树叶子个数]>
void solve1()
{
    for(int i=2;i<=n;i++)
        ans+=2.0/i;
    printf("%.6lf
",ans);
}
void solve2()
{
    f[1][0]=1;
    f[2][1]=1;
    f[3][2]=1;
    for(int i=4;i<=n;i++)//叶子个数 
        for(int j=1;j<i;j++)//左子树叶子个数 
            for(int k=0;k<j;k++)//左子树深度 
                for(int l=0;l<i-j;l++)//右子树深度 
                    f[i][max(k,l)+1]+=f[j][k]*f[i-j][l]/(i-1);
    for(int i=1;i<=n;++i)ans+=i*f[n][i];
    printf("%.6lf
",ans);
}
int main()
{
    scanf("%d%d",&q,&n);
    if(q==1)solve1();
    if(q==2)solve2();
    return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/9132844.html