【期望】CF850F Rainbow Balls

【题目】
CF
袋子里有 n n n种颜色的球,第 i i i个颜色有 a i a_i ai个,当袋子里有两种或以上颜色球时,连续取出两个球,并将第二个球涂成第一个球的颜色,再将两个球放回去。求期望时间对 1 e 9 + 7 1e9+7 1e9+7取模。 n ≤ 2500 , a i ≤ 1 0 5 n\leq 2500,a_i\leq 10^5 n2500,ai105

【解题思路】
s = ∑ a i s=\sum a_i s=ai
首先我们可以枚举最后剩下的颜色,设 f i f_i fi表示当前有 i i i个这种颜色球时,所有球都变成这个颜色的期望,那么 f 0 f_0 f0不存在, f s = 0 f_s=0 fs=0

这个问题实际上可以转化为一个序列上的随机游走问题:一个长度为 s + 1 s+1 s+1的序列,位置编号 0 ∼ s 0\sim s 0s,在 0 &lt; i &lt; s 0&lt;i&lt;s 0<i<s的地方向前后的概率是相等的,在序列的两头会停下来。
这个是一个经典的赌徒破产问题,设状态为当前在某个点到达端点的概率,我们可以将方程表示成常系数线性递推的关系,解特征根方程来做。巧合的是这个问题在考前数学组的同学来问过我然后我随便搞了一下就搞出来了。

由于概率相等比较特殊,我们不妨设从 i i i走到 s s s的概率为 p i p_i pi,那么我们有 p 0 = 0 , p s = 1 , p i = p i − 1 + p i + 1 2 ( 0 &lt; i &lt; s ) p_0=0,p_s=1,p_i=\frac{p_{i-1}+p_{i+1}} 2(0&lt;i&lt;s) p0=0,ps=1,pi=2pi1+pi+1(0<i<s),然后 p i + 1 − p i = p i − p i − 1 p_{i+1}-p_i=p_i-p_{i-1} pi+1pi=pipi1,就是一个等差数列的形式了。

于是不难得到在 i i i点走到 s s s的概率为 i s \frac i s si,那么走到 0 0 0就是 s − i s \frac {s-i} s ssi

这样依赖我们就可以列出 f f f的方程,设 p p p表示选出两个不同色球的概率,那么这里 p = i ( s − i ) s ( s − 1 ) p=\frac {i(s-i)} {s(s-1)} p=s(s1)i(si)
f i = p ( f i − 1 + f i + 1 ) + ( 1 − 2 p ) f i + i s ( 0 &lt; i &lt; s ) f_i=p(f_{i-1}+f_{i+1})+(1-2p)f_i+\frac i s(0&lt;i&lt;s) fi=p(fi1+fi+1)+(12p)fi+si(0<i<s)

这里显然可以高斯消元做到 O ( ( ∑ a i ) 3 ) O((\sum a_i)^3) O((ai)3)

考虑化简这个方程,由于没有 f 0 f_0 f0,我们可以得到:
f 1 = p f 2 + ( 1 − 2 p ) f 1 + 1 s f_1=pf_2+(1-2p)f_1+\frac 1 s f1=pf2+(12p)f1+s1
f 2 = 2 f 1 − 1 f_2=2f_1-1 f2=2f11

又因为(我们将原式移项):
f i − f i + 1 = f i − 1 − f i + s − 1 s − i f_i-f_{i+1}=f_{i-1}-f_i+\frac{s-1}{s-i} fifi+1=fi1fi+sis1
所以有:
f 1 = f 1 − f s = ∑ i = 2 s f i − 1 − f i = ( s − 1 ) ( f 1 − f 2 ) + ∑ i = 2 s − 1 s − 1 s − i ( s − i ) f_1=f_1-f_s=\sum_{i=2}^sf_{i-1}-f_i=(s-1)(f_1-f_2)+\sum_{i=2}^{s-1}\frac {s-1}{s-i}(s-i) f1=f1fs=i=2sfi1fi=(s1)(f1f2)+i=2s1sis1(si)
回代得:
f 1 = ( s − 1 ) 2 s f_1=\frac {(s-1)^2} s f1=s(s1)2
于是我们可以求出 f 2 f_2 f2,然后就可以递推出所有的 f f f了。
最后答案就是 ∑ i = 1 n f a i \sum_{i=1}^n f_{a_i} i=1nfai
复杂度 O ( n + max ⁡ { a i } ) O(n+\max \{a_i\}) O(n+max{ai})

【参考代码】

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

typedef long long ll;
const int N=1e5+10,mod=1e9+7;
int n,mx,sum,ans;
int a[N],f[N];

int qpow(int x,int y)
{
	int res=1;
	for(;y;y>>=1,x=(ll)x*x%mod)if(y&1)res=(ll)res*x%mod;
	return res;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("CF850F.in","r",stdin);
	freopen("CF850F.out","w",stdout);
#endif
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]),mx=max(mx,a[i]),sum+=a[i];
	f[1]=(ll)(sum-1)*(sum-1)%mod*qpow(sum,mod-2)%mod;
	for(int i=1;i<mx;++i) 
		f[i+1]=((ll)f[i]*2-f[i-1]-(ll)(sum-1)*qpow(sum-i,mod-2)%mod+mod*2)%mod;
	for(int i=1;i<=n;++i) ans=(ans+f[a[i]])%mod;
	printf("%d\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值