CF850F Rainbow Balls

首先可以枚举最后的球都是什么颜色

f i f_i fi 表示当前有 i i i 个钦定的颜色的球,把所有球都变成这种颜色的期望时间

显然 f 0 f_0 f0 不存在

s = ∑ i = 1 n a i s=\sum_{i=1}^{n}a_i s=i=1nai 那么 f s = 0 f_s=0 fs=0

对于 0 &lt; i &lt; s 0&lt;i&lt;s 0<i<s 可以得到一个 D P DP DP 方程

f i = ( f i − 1 + f i + 1 ) p + ( 1 − 2 p ) f i + v f_i=(f_{i-1}+f_{i+1})p+(1-2p)f_i+v fi=(fi1+fi+1)p+(12p)fi+v

其中 p p p 表示选出两个球不同色的概率 i ( s − i ) s ( s − 1 ) \frac{i(s-i)}{s(s-1)} s(s1)i(si) v v v 表示贡献的期望时间

注意不是 1 1 1!!!

结论就是 v = i s v=\frac{i}{s} v=si

考虑 v v v 是个什么东西下面纯属瞎bb

由于不能到 0 0 0 这个状态,所以 i i i 只能算到达那些走到 s s s 的贡献

那么 v v v 相当于走到 s s s 的概率,也就是走一步的期望

也就是数轴上一个点 x x x 每次等概率向左或者向右走,求走到 0 0 0 之前到达 s s s 的概率

这个是个经典问题

g i g_i gi 表示 i i i s s s 的概率,那么 g 0 = 0 , g s = 1 g_0=0,g_s=1 g0=0,gs=1

g i = p g i − 1 + p g i + 1 + ( 1 − 2 p ) g i g_i=pg_{i-1}+pg_{i+1}+(1-2p)g_i gi=pgi1+pgi+1+(12p)gi

那么 g i − g i − 1 = g i + 1 − g i g_i-g_{i-1}=g_{i+1}-g_i gigi1=gi+1gi

可以得到概率为 i s \frac{i}{s} si

瞎bb完了

那么现在有一个方程

f i = ( f i − 1 + f i + 1 ) p + ( 1 − 2 p ) f i + i s                            ( 1 ) f_i=(f_{i-1}+f_{i+1})p+(1-2p)f_i+\frac{i}{s} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (1) fi=(fi1+fi+1)p+(12p)fi+si                          (1)

由于 f 0 f_0 f0 不存在那么

f 1 = f 2 p + ( 1 − 2 p ) f 1 + 1 s f_1=f_2p+(1-2p)f_1+\frac{1}{s} f1=f2p+(12p)f1+s1

f 2 = 2 f 1 − 1 f_2=2f_1-1 f2=2f11

( 1 ) (1) (1) 可以得到

f i − f i + 1 = f i − 1 − f i + s − 1 s − i                            ( 2 ) f_i-f_{i+1}=f_{i-1}-f_i+\frac{s-1}{s-i} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (2) fifi+1=fi1fi+sis1                          (2)

所以

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}(s-i) f1=f1fs=i=2sfi1fi=(s1)(f1f2)+i=2s1sis1(si)

代入 f 2 = 2 f 1 − 1 f_2=2f_1-1 f2=2f11 得到

f 1 = ( s − 1 ) 2 s f_1=\frac{(s-1)^2}{s} f1=s(s1)2

那么求出 f 2 f_2 f2 之后,根据 ( 2 ) (2) (2) 就可以推出所有的 f f f

最后答案就是 ∑ i = 1 n f a i \sum_{i=1}^{n}f_{a_i} i=1nfai

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

const int mod(1e9 + 7);
const int maxn(1e5 + 5);

int mx = 1e5, n, cnt[maxn], sum, f[maxn], ans;

inline void Inc(int &x, int y) {
	if ((x += y) >= mod) x -= mod;
}

inline int Pow(ll x, int y) {
	register ll ret = 1;
	for (; y; y >>= 1, x = x * x % mod)
		if (y & 1) ret = ret * x % mod;
	return ret;
}

int main() {
	scanf("%d", &n);
	register int i;
	for (i = 1; i <= n; ++i) scanf("%d", &cnt[i]), sum += cnt[i];
	f[1] = 1LL * (sum - 1) * (sum - 1) % mod * Pow(sum, mod - 2) % mod;
	f[2] = (2 * f[1] % mod + mod - 1) % mod;
	for (i = 2; i < mx; ++i)
		f[i + 1] = ((2 * f[i] % mod - f[i - 1] + mod) % mod - 1LL * (sum - 1) * Pow(sum - i, mod - 2) % mod + mod) % mod;
	for (i = 1; i <= n; ++i) Inc(ans, f[cnt[i]]);
	printf("%d\n", ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值