stone2 [期望]

也许更好的阅读体验

\(\mathcal{Description}\)
\(n\) 堆石子,依次编号为 \(1, 2,\ldots , n\),其中第 \(i\) 堆有 \(a_i\) 颗石子
你每次在仍然有石子的石子堆中等概率随机选择一堆石子,并取走其中一颗石子
求第 \(1\) 堆石子被取走的时间的期望

\(n\leq 5\times 10^5,a_i\leq 5\times 10^5\)

\(\mathcal{Solution}\)
这题其实也不难,然而也不是考虑\(DP\),和stone一样
问题要求的实际就是在第\(1\)堆石子被取完之前,总共有多少个石子被拿走了
显然\(a_1\)被拿完了,再考虑期望的线性性,由于你取走其他堆石子对当前堆没有影响,可以单独考虑每一堆石子被取了多少个

先考虑\(a_i\)没有全部被取完
假设第\(i\)堆石子被取走了\(x\left(0\leq x\leq a_i-1\right)\)颗石子,因为第\(i\)堆石子没被取完,而没有继续被取走肯定是因为第\(1\)堆石子被取完了
\(1\)为从第一堆石子中取一颗石子,\(0\)为从第二堆石子中取一颗石子
那么方案数就是有\(a_1\)\(1\)\(x\)\(0\)的长度为\(a_1+x\)的且最后一位是\(1\)的二进制串的个数
则有\(\begin{pmatrix}a_1+x-1 \\ x\end{pmatrix}\)种方案数,总方案数为\(2^{a_1+x}\),那么概率就是\(p_x=\frac{\begin{pmatrix}a_1+x-1\\ x\end{pmatrix}}{2^{a_1+x}}\)

\(x=a_i\),这个看起来没原来那么好算了,想到这两种情况的概率加起来应该等于\(1\),所以这种情况的概率就是\(q=1-\sum\limits_{j=0}^{a_i-1}p_j\)
则我们得到\(E_i=\sum\limits_{j=0}^{a_i-1}j*p_j+qa_i\)
总期望就是\(E=\sum\limits_{i=2}^nE_i\),写复杂点就是

\(E=\left(\sum\limits_{i=2}^n\left(\sum\limits_{j=0}^{a_i-1}j*\frac{\begin{pmatrix}a_1+j-1 \\ j\end{pmatrix}}{2^{a_1+j}}\right)+a_i\left(1-\sum\limits_{j=0}^{a_i-1}\frac{\begin{pmatrix}a_1+j-1 \\ j\end{pmatrix}}{2^{a_1+j}}\right)\right)+a_1\)

这个东西怎么维护呢,直接考虑\(a_i\)变成\(a_i+1\)的情况,我们考虑里面那个\(\sum\)的变化,实际上只有枚举上界增大\(1\)变成了\(a_i\)我们直接对\(a_i\)的所有取值的答案都预处理出来就行了

\(\mathcal{Code}\)

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年11月08日 星期五 16时20分30秒
*******************************/
#include <cstdio>
#include <fstream>
using namespace std;
const int maxn = 1000006;
const int lim = 1000000;
const int h = 500000;
const int mod = 323232323;
//cin为我打的快读板子,详细内容可去看以前的代码,总是在这里写感觉有点影响阅读
int n,p,ans,a;
int fac[maxn],ifac[maxn],inv[maxn],mi[maxn],f[maxn],g[maxn];
int C (int n,int m){	return 1ll*fac[n]*ifac[n-m]%mod*ifac[m]%mod;}
int main()
{
	fac[0]=ifac[0]=mi[0]=inv[1]=1;
	for (int i=2;i<=lim;++i)	inv[i]=(mod-1ll*mod/i*inv[mod%i]%mod);
	for (int i=1;i<=lim;++i)	fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*inv[i]%mod,mi[i]=1ll*mi[i-1]*inv[2]%mod;

	cin>>n>>a;
	ans=a;

	//枚举上界为i
	g[0]=mi[a];
	for (int i=1;i<=h;++i){
		int p=1ll*C(a+i-1,i)*mi[a+i]%mod;
		f[i]=(f[i-1]+1ll*i*p%mod)%mod;
		g[i]=(g[i-1]+p)%mod;
	}

	//石子数为i的答案
	for (int i=h;i>=1;--i)	f[i]=(f[i-1]+1ll*i*(mod+1-g[i-1])%mod)%mod;

	for (int i=2;i<=n;++i)	cin>>a,ans=(ans+f[a])%mod;

	printf("%d\n",ans);
	return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧

posted @ 2019-11-08 21:27  Morning_Glory  阅读(305)  评论(0编辑  收藏  举报
//