luoguP3830 [SHOI2012]随机树
题目背景
SHOI2012 D1T3
题目描述
输入输出格式
输入格式:
输入仅有一行,包含两个正整数 q, n,分别表示问题编号以及叶结点的个数。
输出格式:
输出仅有一行,包含一个实数 d,四舍五入精确到小数点后 6 位。如果 q = 1,则 d 表示叶结点平均深度的数学期望值;如果 q = 2,则 d 表示树深度的数学期望值。
分析
沉迷概率无法自拔。
第一问:
设
f
(
x
)
f(x)
f(x)为
x
x
x个叶节点的平均深度的期望
考虑选择一个节点拓展
f
(
x
+
1
)
=
x
f
(
x
)
+
f
(
x
)
+
2
x
+
1
=
f
(
x
)
+
2
x
+
1
f(x+1)=\frac{xf(x)+f(x)+2}{x+1}=f(x)+\frac{2}{x+1}
f(x+1)=x+1xf(x)+f(x)+2=f(x)+x+12
递推一下就可以了。
第二问:
介绍一个公式
整数概率公式
E ( x ) = ∑ i = 1 i n f P ( x ≥ i ) E(x)=\sum_{i=1}^{inf}P(x\ge i) E(x)=∑i=1infP(x≥i)
它的意思是:正整数随机变量x的期望等于其分别大于等于所有数的概率之和。
证明:
根据期望的定义式,我们有
E
(
x
)
=
∑
i
=
1
i
n
f
i
P
(
x
=
i
)
=
∑
i
=
1
i
n
f
i
[
P
(
x
≥
i
)
−
P
(
x
≥
i
+
1
)
]
=
∑
i
=
1
i
n
f
P
(
x
≥
i
)
E(x)=\sum_{i=1}^{inf}iP(x=i)=\sum_{i=1}^{inf}i[P(x\ge i)-P(x\ge i +1)]=\sum_{i=1}^{inf}P(x\ge i)
E(x)=∑i=1infiP(x=i)=∑i=1infi[P(x≥i)−P(x≥i+1)]=∑i=1infP(x≥i)
Q
.
E
.
D
Q.E.D
Q.E.D
回到本题,设
f
[
x
]
[
d
]
f[x][d]
f[x][d]表示有
x
x
x个叶子节点深度超过
d
d
d的概率。
考虑某个节点拓展的左右子节点。
用容斥原理可以得到方程。
f
[
x
]
[
d
]
=
f
[
k
]
[
d
−
1
]
+
f
[
x
−
k
]
[
d
−
1
]
−
f
[
k
]
[
d
−
1
]
⋅
f
[
x
−
k
]
[
d
−
1
]
f[x][d]=f[k][d-1]+f[x-k][d-1]-f[k][d-1]\cdot f[x-k][d-1]
f[x][d]=f[k][d−1]+f[x−k][d−1]−f[k][d−1]⋅f[x−k][d−1]
转移一波然后
A
n
s
=
∑
i
=
1
n
−
1
f
[
n
]
[
i
]
Ans=\sum_{i=1}^{n-1}f[n][i]
Ans=∑i=1n−1f[n][i]
代码
#include<cstdio>
const int N = 110;
int ri() {
char ch = getchar(); int x = 0, f = 1;
for(;ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) - '0' + ch;
return x * f;
}
double g[N], f[N][N];
int main() {
int q = ri(), n = ri();
if(q == 1) {
for(int i = 2;i <= n; ++i) g[i] = g[i - 1] + 2.0 / i;
printf("%.6lf\n", g[n]);
}
else {
for(int i = 1;i <= n; ++i) f[i][0] = 1;
for(int i = 2;i <= n; ++i)
for(int j = 1;j < i; f[i][j++] /= i - 1)
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];
double r = 0;
for(int i = 1;i < n; ++i) r += f[n][i];
printf("%.6lf\n", r);
}
return 0;
}