题解 P3830 【[SHOI2012]随机树】
emptysetvvvv · · 题解
数学期望
背景
前人之述备矣,BJpers2神犇的证明更是极为精彩,让小萌新
思路
- 考虑第一问
设
则
故有
即
-
考虑第二问
-
先证明一个小结论:设扩展
i-1 次后,左子树有k 个叶子的概率、右子树有i-k 个叶子的概率为P(k) 。则有\forall k_1,k_2\in[1,i-1],P(k_1)=P(k_2) 。
将扩展过程表示为序列,则其中 “扩展左子树” 有
再考虑
同理,右子树的形态数有
故考虑扩展先后、树的形态,生成一个左子树有
与
- 前置芝士:整数概率公式
正整数随机变量
证明:
E(x)=\sum_{i=1}^{\infty}P(x=i)\cdot i=\sum_{i=1}^{\infty}(P(x\geqslant i)-P(x\geqslant i+1))\cdot i =\sum_{i=1}^{\infty}P(x\geqslant i)\cdot i-P(x\geqslant i)\cdot(i-1)=\sum_{i=1}^{\infty}P(x\geqslant i)
- 计算概率
设
解释如下,首先考虑左、右子树深度不小于
前文我们证明过,左子树叶节点数为
初始条件,
由整数概率公式可知,期望深度
代码
#include <cstdio>
int n, op;
double ans, f[105][105];
void solve1() {
for(int i = 2; i <= n; ++i) ans += 2.0 / i;
}
void solve2() {
for(int i = 1; i <= n; ++i) f[i][0] = 1;
for(int i = 2; i <= n; ++i)
for(int j = 1; j < i; ++j)
for(int k = 1; k < i; ++k)
f[i][j] += (f[k][j-1] + f[i-k][j-1] - f[k][j-1]*f[i-k][j-1]) / (i-1);
for(int i = 1; i < n; ++i) ans += f[n][i];
}
int main() {
scanf("%d %d", &op, &n);
if(op & 1) solve1();
else solve2();
printf("%.6lf\n", ans);
}
p.s
毕竟
没有的话.......求赞【可怜】......