Luogu P3830 SHOI2012 随机树

16 篇文章 0 订阅
6 篇文章 0 订阅

题目

过之前觉得这题紫题实在是评分过低,过了之后才发现这题紫题是评分过高????
首先第1问就开始玄学:
f x f_x fx为x个叶子的期望平均深度,那么你拓展一个叶子的期望增加总深度为 f x + 2 f_x+2 fx+2
f x + 1 = x f x + f x + 2 x + 1 = f x + 2 x f_{x+1} = \frac {xf_x+f_x+2}{x+1}=f_x + \frac 2x fx+1=x+1xfx+fx+2=fx+x2
好巧(气)啊。。。。。。
如果不能接受可以 O ( n 2 ) d p O(n^2)dp O(n2)dp出有一个深度恰好为d的叶子的概率再乘上d算个总和就行。。。

第二问:
发现这个不好dp,开始拆:
首先是期望拆成概率:
E ( a n s ) = ∑ i = 1 ∞ i P ( i = x ) = ∑ i = 1 ∞ i ( P ( x > = i ) − P ( x > = i + 1 ) ) = ∑ i = 1 ∞ P ( x > = i ) E(ans) = \sum_{i=1}^{\infty}iP(i=x)\\=\sum_{i=1}^{\infty}i(P(x>=i)-P(x>=i+1))\\=\sum_{i=1}^{\infty}P(x>=i) E(ans)=i=1iP(i=x)=i=1i(P(x>=i)P(x>=i+1))=i=1P(x>=i)
然后发现深度大于i的概率还是不好求。
继续拆:
我们发现随机树的生成方式对计数很不友好,把他拆出来。
(莫名其妙)发现树的左右子树内操作次数固定的情况下(条件概率)深度大于等于一个数的概率,和生成方式生成满足这树左右操作次数的概率是独立的。
那就考虑两个怎么分别求。
考虑二叉树式dp:
d p [ i ] [ j ] dp[i][j] dp[i][j]为i次操作的子树深度大于等于j。
自然想到枚举左子树的操作次数。
设左子树操作次数为k,
那么(在左子树操作次数为k的情况下)深度大于等于j的概率为:
d p [ k ] [ j − 1 ] + d p [ i − k − 1 ] [ j − 1 ] − d p [ k ] [ j − 1 ] ∗ d p [ i − k − 1 ] [ j − 1 ] dp[k][j-1] + dp[i-k-1][j-1] - dp[k][j-1] *dp[i-k-1][j-1] dp[k][j1]+dp[ik1][j1]dp[k][j1]dp[ik1][j1]
然后再看左子树操作次数为k,右子树操作次数为i-1-k的概率。
发现这个有点像插空法,考虑用方案数/总方案数。
方案数为:
左子树确定一个顺序: k ! k! k!
右子树确定一个顺序: ( i − k − 1 ) ! (i-k-1)! (ik1)!
左右子树相间方案:在 i − 1 i-1 i1个盒子中选 k k k个作为左子树, ( k i − 1 ) \binom{k}{i-1} (i1k)
三个相乘发现是 ( i − 1 ) ! (i-1)! (i1)!
再除总方案数 i ! i! i! 1 i \frac 1i i1
然后就完美解决了???

AC Code:

#include<bits/stdc++.h>
#define maxn 105
using namespace std;

int p,n;
double dp[maxn][maxn];

int main()
{
	scanf("%d%d",&p,&n);
	if(p == 1)
	{
		double ans = 0;
		for(int i=2;i<=n;i++)
			ans = ans + 2.0 / i;
		printf("%.6lf",ans);
	}
	else
	{
		dp[0][0] = 1;
		for(int i=1;i<n;i++)
		{
			for(int dep=1;dep<=n;dep++)
			{
				for(int j=0;j<i;j++)
				{
					dp[i][dep] += dp[j][dep-1] + dp[i-1-j][dep-1] - dp[j][dep-1] * dp[i-1-j][dep-1];
				}
				dp[i][dep] /= i;
			}
			dp[i][0] = 1;
		}
		double ans = 0;
		for(int i=1;i<=n;i++)
			ans += dp[n-1][i];
		printf("%.6lf",ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值