CF850F Rainbow Balls(数学、期望)

解析

二倍相邻项,就要想裂项

纯数学题
一道黑色的小凯的疑惑

设总球数为 s s s
我们先钦定一种颜色留到最后,那么其他颜色可以等价考虑
f i f_{i} fi 为钦定的颜色的球有 i i i 个,涂完需要的期望次数
则有:
f i = ( f i − 1 + f i + 1 ) × p + f i × ( 1 − 2 p ) + w i f_i=(f_{i-1}+f_{i+1})\times p+f_i\times (1-2p)+w_i fi=(fi1+fi+1)×p+fi×(12p)+wi
其中 p p p 表示有序取出两个不同色球的概率, w i w_i wi 表示有 i i i 个球的颜色留到最后的概率。
不难发现 p = i ( s − i ) s ( s − 1 ) p=\dfrac{i(s-i)}{s(s-1)} p=s(s1)i(si),考虑如何求 w i w_i wi
首先有: w 0 = 0 , w s = 1 w_0=0,w_s=1 w0=0,ws=1
f f f 的转移类似的,有: w i = ( w i − 1 + w i + 1 ) × p + w i × ( 1 − 2 p ) w_i=(w_{i-1}+w_{i+1})\times p+w_i\times (1-2p) wi=(wi1+wi+1)×p+wi×(12p)
化简移项,得:
w i + 1 − w i = w i − w i − 1 w_{i+1}-w_i=w_i-w_{i-1} wi+1wi=wiwi1
也就是说 w w w 是一个等差数列,那么显然就有:
w i = i s w_i=\frac{i}{s} wi=si
p , w p,w p,w 带回原来的转移式:
f i = ( f i − 1 + f i + 1 ) × i ( s − i ) s ( s − 1 ) + f i × ( 1 − 2 i ( s − i ) s ( s − 1 ) ) + i s f_i=(f_{i-1}+f_{i+1})\times \dfrac{i(s-i)}{s(s-1)}+f_i\times (1-\dfrac{2i(s-i)}{s(s-1)})+\frac{i}{s} fi=(fi1+fi+1)×s(s1)i(si)+fi×(1s(s1)2i(si))+si
化简,得:
2 f i = f i + 1 + f i − 1 + s − 1 s − i 2f_i=f_{i+1}+f_{i-1}+\frac{s-1}{s-i} 2fi=fi+1+fi1+sis1
也就是:
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
i = 1 i=1 i=1 带入,有:
f 2 = 2 f 1 − 1 f_2=2f_1-1 f2=2f11
又有:
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}^s(f_{i-1}-f_i)=(s-1)(f_1-f_2)+\sum_{i=2}^{s-1}\frac{s-1}{s-i}\times(s-i) f1=f1fs=i=2s(fi1fi)=(s1)(f1f2)+i=2s1sis1×(si)
后面那个和式是由于对于一个 s − 1 s − i \dfrac{s-1}{s-i} sis1,它会产生 s − i s-i si 次贡献。
f 2 = 2 f 1 + 1 f_2=2f_1+1 f2=2f1+1 带入,得到:
f 1 = ( s − 1 ) 2 s f_1=\frac{(s-1)^2}{s} f1=s(s1)2
得到 f 1 f_1 f1 之后,后面顺推即可。
过程中快速幂求逆元,时间复杂度 O ( n log ⁡   m o d   ) O(n\log \bmod) O(nlogmod)

代码

(式子推完代码几乎没有任何难度了…)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=2e5+100;
const int mod=1e9+7;
inline ll read(){
	ll x(0),f(1);char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int n,m;

inline ll ksm(ll x,ll k){
	ll res(1);
	while(k){
		if(k&1) res=res*x%mod;
		x=x*x%mod;k>>=1;
	}
	return res;
}
ll a[N];
ll s,f[N],mx;

signed main() {
#ifndef ONLINE_JUDGE
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
#endif
	n=read();
	for(int i=1;i<=n;i++) a[i]=read(),s+=a[i],mx=max(mx,a[i]);
	f[1]=(s-1)*(s-1)%mod*ksm(s,mod-2)%mod;
	f[2]=(2*f[1]-1+mod)%mod;
	for(int i=2;i<mx;i++) f[i+1]=(2*f[i]-f[i-1]+mod-(s-1)*ksm(s-i,mod-2)%mod+mod)%mod;
	ll ans(0);
	for(int i=1;i<=n;i++) (ans+=f[a[i]])%=mod;
	printf("%lld\n",ans);
	return 0;
}
/*
*/
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值