連接ios
分析: git
第一問:f[i]表示有i個葉子結點的時候的平均深度,$f[i] = \frac{f[i - 1] + 2 + f[i - 1] * (i - 1)}{2} $,表示新增長一個葉子結點,深度增長2,加權後取平均值。spa
第二問:f[i][j]表示有i個葉子結點,樹的深度大於等於j的機率,有$f[i][max(k, l)+ 1] = \frac{f[j][k] \times f[i - j][l]}{i - 1}$,$ans=\sum\limits_{i = 1}^{n} i * f[n][i]$。code
其中除以$i-1$表示i個葉子結點中,左兒子爲j個時候的機率。由於左兒子結點只有$i-1$個取值,因而每一個的機率都是$\frac{1}{i-1}$。blog
枚舉完左兒子的葉子結點,右兒子葉子結點也就肯定了,而後左右兒子結點都是一個相同的子問題。get
代碼:string
#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\n", 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\n", ans); } int main() { int ty = read(), n = read(); ty == 1 ? solve1(n) : solve2(n); return 0; }