P3830随机树(概率dp,好难啊!)

传送门

题目描述:

原博客

 

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10000005;
const int inf = 0x3f3f3f3f;
const int mod = 19260817;
int q, n;
double f[maxn], dp[105][105];
int main() {
    //freopen("test.txt", "r", stdin);
    scanf("%d%d", &q, &n);
    if (q == 1) {
        f[1] = 0;
        for (int i = 2; i <= n; i++) {
            f[i] = f[i - 1] + 2.0 / i;
        }
        printf("%.6lf\n", f[n]);
    }
    else {
        //dp[i][j]表示i个叶子,高度大于等于j的概率
        for (int i = 1; i <= n; i++) {//高度大于等于0是必然的
            dp[i][0] = 1;
        }
        for (int i = 2; i <= n; i++) {//
            for (int j = 1; j < i; j++) {
                for (int k = 1; k < i; k++) {//对i-1种可能的情况下的概率求和
                    //左子树和右子树在不同高度下的概率
                    dp[i][j] += dp[k][j - 1] + dp[i - k][j - 1] - dp[k][j - 1] * dp[i - k][j - 1];
                }
                dp[i][j] /= double(i-1);//除去i-1得到期望概率
            }
        }
        double ans = 0;
        for (int i = 1; i < n; i++) {//对叶子数为n的不同高度下的概率求和即是期望高度(别问为什么,问就是不知道).
            ans += dp[n][i];
        }
        printf("%.6lf\n", ans);
    }
    return 0;
}

 

posted @ 2021-04-28 14:58  cono奇犽哒  阅读(50)  评论(0编辑  收藏  举报