zoukankan      html  css  js  c++  java
  • P3830 [SHOI2012]随机树

    P3830 [SHOI2012]随机树

    链接

    分析: 

      第一问:f[i]表示有i个叶子结点的时候的平均深度,$f[i] = frac{f[i - 1] + 2 + f[i - 1] * (i - 1)}{2} $,表示新增加一个叶子结点,深度增加2,加权后取平均值。

      第二问:f[i][j]表示有i个叶子结点,树的深度大于等于j的概率,有$f[i][max(k, l)+ 1] = frac{f[j][k] imes f[i - j][l]}{i - 1}$,$ans=sumlimits_{i = 1}^{n} i * f[n][i]$。

      其中除以$i-1$表示i个叶子结点中,左儿子为j个时候的概率。因为左儿子结点只有$i-1$个取值,于是每个的概率都是$frac{1}{i-1}$。

      枚举完左儿子的叶子结点,右儿子叶子结点也就确定了,然后左右儿子结点都是一个相同的子问题。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<map>
    #include<vector>
    #include<bitset>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 1005;
    void solve1(int n) {
        static double f[N];
        for (int i = 2; i <= n; ++i) f[i] = f[i - 1] + 2.0 / i;
        printf("%.6lf
    ", f[n]);
    }
    void solve2(int n) {
        static double f[N][N];
        f[1][0] = 1.0;
        for (int i = 2; 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);
        double ans = 0;
        for (int i = 1; i <= n; ++i) ans += i * f[n][i];
        printf("%.6lf
    ", ans);
    }
    int main() {
        int ty = read(), n = read();
        ty == 1 ? solve1(n) : solve2(n);    
        return 0;
    }
  • 相关阅读:
    C++ String详解
    乏力的编码很累,这里有私货..
    给自己~~微语&&歌单
    2019CSP-J第二轮 B题C题
    HDU 3966 树链剖分+树状数组 模板
    HDU 2255 KM算法 二分图最大权值匹配
    HDU 4280 ISAP+BFS 最大流 模板
    HDU 6181 第k短路
    假装会python--爬取贴吧正文
    HDU 6170 dp
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10635323.html
Copyright © 2011-2022 走看看