stone2 [期望]

也許更好的閱讀體驗

Description\mathcal{Description}
nn 堆石子,依次編號爲 1,2,,n1, 2,\ldots , n,其中第 ii 堆有 aia_i 顆石子
你每次在仍然有石子的石子堆中等概率隨機選擇一堆石子,並取走其中一顆石子
求第 11 堆石子被取走的時間的期望

n5×105,ai5×105n\leq 5\times 10^5,a_i\leq 5\times 10^5

Solution\mathcal{Solution}
這題其實也不難,然而也不是考慮DPDP,和stone一樣
問題要求的實際就是在第11堆石子被取完之前,總共有多少個石子被拿走了
顯然a1a_1被拿完了,再考慮期望的線性性,由於你取走其他堆石子對當前堆沒有影響,可以單獨考慮每一堆石子被取了多少個

先考慮aia_i沒有全部被取完
假設第ii堆石子被取走了x(0xai1)x\left(0\leq x\leq a_i-1\right)顆石子,因爲第ii堆石子沒被取完,而沒有繼續被取走肯定是因爲第11堆石子被取完了
11爲從第一堆石子中取一顆石子,00爲從第二堆石子中取一顆石子
那麼方案數就是有a1a_111xx00的長度爲a1+xa_1+x的且最後一位是11的二進制串的個數
則有(a1+x1x)\begin{pmatrix}a_1+x-1 \\ x\end{pmatrix}種方案數,總方案數爲2a1+x2^{a_1+x},那麼概率就是px=(a1+x1x)2a1+xp_x=\frac{\begin{pmatrix}a_1+x-1\\ x\end{pmatrix}}{2^{a_1+x}}

x=aix=a_i,這個看起來沒原來那麼好算了,想到這兩種情況的概率加起來應該等於11,所以這種情況的概率就是q=1j=0ai1pjq=1-\sum\limits_{j=0}^{a_i-1}p_j
則我們得到Ei=j=0ai1jpj+qaiE_i=\sum\limits_{j=0}^{a_i-1}j*p_j+qa_i
總期望就是E=i=2nEiE=\sum\limits_{i=2}^nE_i,寫複雜點就是

E=(i=2n(j=0ai1j(a1+j1j)2a1+j)+ai(1j=0ai1(a1+j1j)2a1+j))+a1E=\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

這個東西怎麼維護呢,直接考慮aia_i變成ai+1a_i+1的情況,我們考慮裏面那個\sum的變化,實際上只有枚舉上界增大11變成了aia_i我們直接對aia_i的所有取值的答案都預處理出來就行了

Code\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;
}

如有哪裏講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章