P3830 [SHOI2012]随机树

P3830 [SHOI2012]随机树

题解

题意

题面

解法

首先解决第一个问题,叶节点平均深度的期望值,可以设fif_i表示有ii个叶子节点的随机树的平均深度的期望值,可以得到转移方程为

fi=fi1×(i1)fi1+(fi1+1)×2if_i = \frac{f_{i - 1} \times (i - 1) - f_{i - 1} + (f_{i - 1} + 1) \times 2}{i}

其实就是计算当前有ii个叶子节点时在i1i - 1个叶子节点的情况下,展开一个节点,计算其深度的影响,化简后也就是

fi=fi1+2if_i= f_{i- 1} + \frac{2} {i}

然后第二个问题就麻烦了,树深度的期望值,首先根据期望的线性性有

E(x)=i=1+P(ix)E(x) = \sum_{i = 1} ^ {+ \infty} P(i \le x)

然后可以设fi,jf_{i, j}为有ii个叶子节点且深度大于等于jj的树的出现概率,得出转移方程为

fi,j=k=1i1fk,j1+fik,j1fk,j1×fik,j1i1f_{i, j} = \sum_{k = 1} ^ {i - 1} \frac{f_{k, j - 1} + f_{i - k, j - 1} - f_{k, j - 1} \times f_{i - k, j - 1}}{i- 1}

首先kk时枚举的左子树中叶子节点的数量,然后求左子树中深度大于等于j1j - 1 的概率,由于左右子树深度都大于j1j - 1的情况在fk,j1f_{k , j - 1}fik,j1f_ {i - k, j - 1}中都统计过,所以要去减去重复的部分,对于除以i1i - 1的部分可以去看这个证明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>

using namespace std;

const int N = 110;

int n, q;

namespace SubTask1
{
double f[N];

void getans()
{
for(int i = 2; i <= n; i++)
f[i] = f[i - 1] + 2.0 / i;
printf("%.6lf", f[n]);
}
}

namespace SubTask2
{
double f[N][N];

void getans()
{
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];
f[i][j] /= (i - 1) * 1.0;
}
}
double ans = 0;
for(int i = 1; i < n; i++)
ans += f[n][i];
printf("%.6lf", ans);
}
}

int main()
{
scanf("%d%d", &q, &n);
if(q == 1)SubTask1::getans();
if(q == 2)SubTask2::getans();
return 0;
}
作者

Jekyll_Y

发布于

2022-11-01

更新于

2023-03-02

许可协议

评论