题目
思路
第一步转化:分类讨论。每个颜色提供的贡献是独立可加的。
枚举某种颜色最后胜利,则其余颜色可视为相同。于是只需要求出该颜色的数量为 k k k 时的信息。
首先令 f ( x ) f(x) f(x) 表示结束的概率。注意到该颜色减少和增加的概率是相同的,都是 x ( n − x ) n ( n − 1 ) x(n-x)\over n(n-1) n(n−1)x(n−x),因此必定有方程式
显然,这就是数量增加
1
1
1 (与减少
1
1
1 )的概率,写出递推方程式
f
(
x
)
=
f
(
x
−
1
)
+
f
(
x
+
1
)
2
f(x)=\frac{f(x{-}1)+f(x{+}1)}{2}
f(x)=2f(x−1)+f(x+1)
这个式子是等差数列的另一种表示方法,结合边界条件
f
(
0
)
=
0
,
f
(
n
)
=
1
f(0)=0,\;f(n)=1
f(0)=0,f(n)=1 可知
f
(
x
)
=
x
n
f(x)=\frac{x}{n}
f(x)=nx
然后令
g
(
x
)
g(x)
g(x) 表示期望。令
p
x
=
x
(
n
−
x
)
n
(
n
−
1
)
p_x={x(n-x)\over n(n-1)}
px=n(n−1)x(n−x),则
g
(
x
)
=
(
1
−
2
p
x
)
g
(
x
)
+
p
x
[
g
(
x
−
1
)
+
g
(
x
+
1
)
]
+
f
(
x
)
g(x)=(1-2p_x)g(x)+p_x[g(x{-}1)+g(x{+}1)]+f(x)
g(x)=(1−2px)g(x)+px[g(x−1)+g(x+1)]+f(x)
这与上面的式子是等价的。注意是 + f ( x ) +f(x) +f(x),尽管这是常识,但容易忘。
方程可以变形为
2
g
(
x
)
−
g
(
x
−
1
)
−
g
(
x
+
1
)
=
f
(
x
)
p
x
(1)
2g(x)-g(x{-}1)-g(x{+}1)=\frac{f(x)}{p_x}\tag{1}
2g(x)−g(x−1)−g(x+1)=pxf(x)(1)
边界是 g ( 0 ) = g ( n ) = 0 g(0)=g(n)=0 g(0)=g(n)=0 。这玩意儿转移有环;怎么解方程?
生成函数
记
H
(
x
)
=
∑
k
⩾
1
f
(
k
)
p
k
x
k
+
1
H(x)=\sum_{k\geqslant 1}\frac{f(k)}{p_k}x^{k+1}
H(x)=∑k⩾1pkf(k)xk+1,显然答案的生成函数为
G
(
x
)
=
−
H
(
x
)
+
x
g
(
1
)
(
1
−
x
)
2
G(x)=\frac{-H(x)+xg(1)}{(1-x)^2}
G(x)=(1−x)2−H(x)+xg(1)
我们只需解 g ( 1 ) g(1) g(1) 使得 [ x n ] G ( x ) = 0 [x^n]G(x)=0 [xn]G(x)=0 。
H
(
x
)
H(x)
H(x) 没有闭形式,我们就不要再考虑
G
F
\rm GF
GF 了,回到普通计算数学上面来。
[
x
n
]
G
(
x
)
=
n
g
(
1
)
−
∑
i
=
k
n
−
1
f
(
k
)
p
k
(
n
−
k
)
=
n
g
(
1
)
−
(
n
−
1
)
2
[x^n]G(x)=ng(1)-\sum_{i=k}^{n-1}\frac{f(k)}{p_k}(n{-}k)=ng(1)-(n{-}1)^2
[xn]G(x)=ng(1)−i=k∑n−1pkf(k)(n−k)=ng(1)−(n−1)2
于是解出了 g ( 1 ) = ( n − 1 ) 2 n g(1)={(n-1)^2\over n} g(1)=n(n−1)2,就知足吧。
花絮:我非要拼凑 H ( x ) H(x) H(x) 闭形式,因此将 G ( x ) G(x) G(x) 翻转并递推,就会解出 g ( n − 1 ) = n ( H n − 1 ) g(n{-}1)=n(H_{n}{-}1) g(n−1)=n(Hn−1),其中 H n = ∑ j = 1 n 1 j H_n=\sum_{j=1}^{n}\frac{1}{j} Hn=∑j=1nj1 是调和级数,没有快速求解的方法。
初等方法
称 ( 1 ) (1) (1) 式为关于 x x x 的方程。
设
1
⩽
l
⩽
r
⩽
n
1\leqslant l\leqslant r\leqslant n
1⩽l⩽r⩽n 。对所有
k
∈
[
l
,
r
]
k\in[l,r]
k∈[l,r],将
k
k
k 的方程求和(等式左右分别相加),则有
g
(
l
)
+
g
(
r
)
−
g
(
l
−
1
)
−
g
(
r
+
1
)
=
∑
k
=
l
r
f
(
k
)
p
k
g(l)+g(r)-g(l{-}1)-g(r{+}1)=\sum_{k=l}^{r}\frac{f(k)}{p_k}
g(l)+g(r)−g(l−1)−g(r+1)=k=l∑rpkf(k)
令
l
=
1
l=1
l=1 就得到
g
(
1
)
+
g
(
r
)
=
g
(
0
)
+
g
(
r
+
1
)
+
∑
k
=
1
r
f
(
k
)
p
k
g(1)+g(r)=g(0)+g(r{+}1)+\sum_{k=1}^{r}\frac{f(k)}{p_k}
g(1)+g(r)=g(0)+g(r+1)+k=1∑rpkf(k)
联立 g ( 0 ) = 0 g(0)=0 g(0)=0 就有
g ( x ) = g ( x + 1 ) − g ( 1 ) + ∑ i = 1 k f ( k ) p k g(x)=g(x{+}1)-g(1)+\sum_{i=1}^{k}\frac{f(k)}{p_k} g(x)=g(x+1)−g(1)+i=1∑kpkf(k)
注意到它描述的其实是
Δ
g
\Delta g
Δg 。那么求和容易得到
g
(
x
)
=
g
(
n
)
−
(
n
−
x
)
g
(
1
)
+
∑
i
=
x
n
−
1
∑
j
=
1
i
f
(
j
)
p
j
g(x)=g(n)-(n{-}x)g(1)+\sum_{i=x}^{n-1}\sum_{j=1}^{i}\frac{f(j)}{p_j}
g(x)=g(n)−(n−x)g(1)+i=x∑n−1j=1∑ipjf(j)
取 x = 1 x=1 x=1 后化简式子可知 g ( 1 ) = ( n − 1 ) 2 n g(1)={(n-1)^2\over n} g(1)=n(n−1)2 。
代码
这里放出 CF850F Rainbow Balls 的代码。复杂度可以做到线性,但没必要。
#include <cstdio>
#include <algorithm> // Almighty XJX yyds!!
#include <cstring> // oracle: ZXY yydBUS!!!
#include <cctype> // rainybunny root of the evil.
using llong = long long;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
# define rep0(i,a,b) for(int i=(a); i!=(b); ++i)
inline int readint(){
int a = 0, c = getchar(), f = 1;
for(; !isdigit(c); c=getchar()) if(c == '-') f = -f;
for(; isdigit(c); c=getchar()) a = a*10+(c^48);
return a*f;
}
const int MAXA = 100000, MOD = 1e9+7;
inline llong qkpow(llong b, int q){
llong a = 1;
for(; q; q>>=1,b=b*b%MOD) if(q&1) a = a*b%MOD;
return a;
}
const int MAXN = 2500;
int a[MAXN+1], inv[MAXA+1];
int g[MAXA+1];
int main(){
int n = readint(), s = 0;
rep(i,1,n) s += (a[i] = readint());
rep(i,0,MAXA) inv[i] = int(qkpow(s-i,MOD-2));
g[0] = 0, g[1] = int(llong(s-1)*(s-1)%MOD*inv[0]%MOD);
rep0(i,1,MAXA){
g[i+1] = int((llong(g[i]<<1)-g[i-1]
-llong(s-1)*inv[i])%MOD);
if(g[i+1] < 0) g[i+1] += MOD;
}
int ans = 0;
rep(i,1,n) ans = (ans+g[a[i]])%MOD;
printf("%d\n",ans);
return 0;
}