• Luogu P3830 [SHOI2012]随机树 | 期望 DP


    题目链接

    第$1$问

    设$g(i)$为当有$i$个叶节点时,树的叶节点的平均深度的期望值。

    假如现在有$(i-1)$个叶节点,现在要等概率地展开一个叶节点,那么展开的那个叶节点的期望深度为$g(i-1)$,展开后那两个新的叶节点的期望深度均为$(g(i-1)+1)$,叶节点深度总和的期望值增加了$(g(i-1)+2)$。

    所以,$g(i)=dfrac{(i-1)g(i-1)+g(i-1)+2}{i}=g(i-1)+dfrac{2}{i}$

    边界:$g(1)=0$

    第$2$问

     设$f(i,j)$为当有$i$个叶节点时,树的深度大于等于$j$的概率。

    假设现在有$i$个叶节点,树的深度大于等于$j$。

    考虑枚举根节点左子树中叶节点的个数,假设有$k$个,则根节点右子树中叶节点的个数为$(i-k)$个。

    现在要计算生成这样一棵树的概率是多少。

    我们不妨先计算生成这样一棵树有多少种方案。

    对于第一次展开,一定是展开根节点。

    第一次展开后,左子树中还要展开$(k-1)$次,右子树中还要展开$(i-k-1)$次。

    显然,从一个节点开始,展开$x$次的方案数有$x!$种。

    那么,左子树展开的方案数即有$(k-1)!$种,右子树展开的方案数即有$(i-k-1)!$种。

    对于每一次展开,我们既可以展开左子树中的叶节点,也可以展开右子树中的叶节点。

    综上,生成一棵这样的树的方案数为

    $(k-1)!(i-k-1)!C_{k-1+i-k-1}^{k-1}=(k-1)!(i-k-1)!dfrac{(i-2)!}{(k-1)!(i-k-1)!}=(i-2)!$

    所以,生成一棵根节点的左子树中有$k$个叶节点,右子树中有$(i-k)$个叶节点的树的方案数为$(i-2)!$,与$k$无关。

    因为$1leqslant k leqslant i-1$且$k$为整数,且对于每一个$k$,方案数均为$(i-2)!$。

    所以,生成一棵根节点的左子树中有$k$个叶节点,右子树中有$(i-k)$个叶节点的树的概率为$dfrac{1}{i-1}$。

    接着我们就来考虑,对于一棵根节点的左子树中有$k$个叶节点,右子树中有$(i-k)$个叶节点的树,树的深度大于等于$j$的概率是多少。

    显然为$f(k,j-1)+f(i-k,j-1)-f(k,j-1)cdot f(i-k,j-1)$

    所以$f(i,j)=sumlimits_{k=1}^{i-1}(f(k,j-1)+f(i-k,j-1)-f(k,j-1)cdot f(i-k,j-1))cdotdfrac{1}{i-1}$ 

    边界:$f(i,0)=1(1leqslant i leqslant n)$

    $ans=sumlimits_{i=1}^{n-1}i(f(n,i)-f(n,i+1))$

    #include<iostream>
    #include<cstdio>
        using namespace std;
        double g[105],f[105][105];
    int main()
    {
        int q=0,n=0;
        scanf("%d%d",&q,&n);
        if(q==1)
        {
            g[1]=0;
            for(int i=2;i<=n;i++)
                g[i]=g[i-1]+(double)2/i;
            printf("%.6f",g[n]);
        }
        if(q==2)
        {
            for(int i=1;i<=n;i++) f[i][0]=1;
            for(int i=2;i<=n;i++)
                for(int j=1;j<=i-1;j++)
                    for(int k=1;k<=i-1;k++)
                        f[i][j]+=(f[k][j-1]+f[i-k][j-1]-f[k][j-1]*f[i-k][j-1])/(i-1);
            double ans=0;
            for(int i=1;i<=n-1;i++)
                ans+=i*(f[n][i]-f[n][i+1]);
            printf("%.6f",ans);
        }
        return 0;
    }
    Luogu P3830
  • 相关阅读:
    CoreData学习-最好的一片文章
    Xcode4.6下添加百度地图ios版(BMapKit)详细教程(_BMKMapManager错误解决)
    NSSearchPathForDirectoriesInDomains用法
    编绎显示Unknown type name “CGFloat” 错误解决方法
    自动调整cell的高度
    sqlMapConfig约束
    PotPlayer左上角信息关闭
    松懈
    sql查询练习
    idea内容补充
  • 原文地址:https://www.cnblogs.com/wozaixuexi/p/11237850.html
Copyright © 2020-2023  润新知