【XSY3409】树(概率与期望,思维)

考虑累加种下第 i i i 棵不同的树树到种下第 i + 1 i+1 i+1 棵不同的树之间的时间间隔,设 f ( i ) f(i) f(i) 表示种了 i i i 棵不同的树游戏仍未结束的概率,那么有:
a n s = ∑ i = 0 n − 1 f ( i ) ( ∑ t = 0 ∞ ( i n ) t ( 1 − i n ) ( t + 1 ) ) = ∑ i = 0 n − 1 n n − i f ( i ) \begin{aligned} ans&=\sum_{i=0}^{n-1}f(i)\left(\sum_{t=0}^{\infty}\left(\frac{i}{n}\right)^t\left(1-\frac{i}{n}\right)(t+1)\right)\\ &=\sum_{i=0}^{n-1}\frac{n}{n-i}f(i) \end{aligned} ans=i=0n1f(i)(t=0(ni)t(1ni)(t+1))=i=0n1ninf(i)
g ( i ) g(i) g(i) 表示恰好在种了 i i i 棵不同的树时游戏结束的概率,那么有 f ( i ) = 1 − ∑ j ≤ i g ( j ) f(i)=1-\sum_{j\leq i}g(j) f(i)=1jig(j)

考虑恰好在种了 i i i 棵不同的树时游戏结束的情形会是怎样:有 i i i 个位置是我们种的树,剩下 n − i n-i ni 个位置是它们自己长出来的(称这些位置为空位置),我们需要保证这 n − i n-i ni 个空位置不能相邻(否则长不出来)。把符合这种条件的游戏情形称为 ”结束情形“。

考虑先把这 n − i n-i ni 个位置选出来,概率为 ( i n − i ) ( n − 1 i − 1 ) \dfrac{\binom{i}{n-i}}{\binom{n-1}{i-1}} (i1n1)(nii)

当然也有可能一些本来我们要种树的地方它自己长出来了,导致游戏提前结束,所以这部分的概率要剪掉。而发现当存在空位置相邻时游戏一定不可能结束,所以(在我们限制的情形下,游戏提前结束的概率)就等于(游戏提前结束的概率),即游戏不可能在我们限制的情形之外提前结束,于是直接减掉 ∑ j < i g ( j ) \sum_{j<i}g(j) j<ig(j) 即可,即:
g ( i ) = ( i n − i ) ( n − 1 i − 1 ) − ∑ j < i g ( j ) g(i)=\dfrac{\binom{i}{n-i}}{\binom{n-1}{i-1}}-\sum_{j<i}g(j) g(i)=(i1n1)(nii)j<ig(j)
你发现 f ( i ) f(i) f(i) 刚好等于 ( i n − i ) ( n − 1 i − 1 ) \dfrac{\binom{i}{n-i}}{\binom{n-1}{i-1}} (i1n1)(nii),即把 n − i n-i ni 个位置选出来的概率。

另一种解释是:考虑在所有树都长出来的情况下 ”宣布“ 游戏结束,但仍能继续种树,那么之后无论我怎么种树总是满足 ”结束情形“ 的要求。所以前 i i i 轮中 ”宣布“ 了游戏结束的概率就等于第 i i i 轮时的情形满足 ”结束情形“ 要求的概率。

#include<bits/stdc++.h>

#define N 10000010

using namespace std;

namespace modular
{
	const int mod=1000000007;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
	inline void Add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
}using namespace modular;

inline int poww(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int n,fac[N],ifac[N];

inline int inv(int x)
{
	return mul(ifac[x],fac[x-1]);
}

inline int C(int n,int m)
{
	return mul(mul(fac[n],ifac[m]),ifac[n-m]);
}

inline int invC(int n,int m)
{
	return mul(mul(ifac[n],fac[m]),fac[n-m]);
}

int main()
{
	n=read();
	fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
	ifac[n]=poww(fac[n],mod-2);
	for(int i=n;i>=1;i--) ifac[i-1]=mul(ifac[i],i);
	int ans=0;
	for(int i=0;i<n;i++)
		Add(ans,mul(inv(n-i),i>=n-(n/2)?dec(1,mul(C(i,n-i),invC(n-1,i-1))):1));
	printf("%d\n",mul(ans,n));
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值