[SHOI2012]随机树

版权声明:欢迎转载(标记出处),写得不好还请多指教 https://blog.csdn.net/quan_tum/article/details/82792081

传送门

这里来的思路

第一问:

a x a_x 表示有 x x 个叶子节点的树的叶子节点平均深度,在一个有 x 1 x-1 个叶子节点的树里随机选择一个叶子节点展开,树的叶子节点深度总和会增加 a [ x 1 ] + 2 a[x-1]+2

第二问:

f [ i ] [ j ] f[i][j] 表示有 i i 个叶子,树的深度 j \geq j 的概率,转移时枚举左右子树有多少个叶子: f [ i ] [ j ] = k = 1 i 1 1 i 1 ( f [ k ] [ j 1 ] + f [ i k ] [ j 1 ] f [ k ] [ j 1 ] × f [ i k ] [ j 1 ] ) f[i][j]=\sum_{k=1}^{i-1}\frac{1}{i-1}(f[k][j-1]+f[i-k][j-1]-f[k][j-1]\times f[i-k][j-1])
两边都 j 1 \geq j-1 的情况要减掉

最后答案为 i = 1 n 1 f [ n ] [ i ] \sum_{i=1}^{n-1}f[n][i]

#include<bits/stdc++.h>
using namespace std;
int p,n;double a[105],f[105][105],ans;
int main(){
	scanf("%d%d",&p,&n);
	if(p==1){
		for(int i=2;i<=n;i++) a[i]=a[i-1]+2.0/i;
		return !printf("%.6f",a[n]);
	}
	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);
	}
	for(int i=1;i<n;++i) ans+=f[n][i];
	return !printf("%.6f",ans);
}

猜你喜欢

转载自blog.csdn.net/quan_tum/article/details/82792081
今日推荐