考虑停在每个人的贡献。设 (E_i) 表示最终停在第 (i) 个人的 概率 ( imes) 步数 之和,那么 (Ans = sum_{i}E_i)。但是 (E_i) 仍然不好算,因为中间可能突然停到了另一个人上。于是我们设 (E_i') 表示假设只有在第 (i) 个人处集齐才停止的期望步数,那么就可以用类似随机游走的模型来方便地搞了。
考虑 (E) 和 (E') 的关系:
[E_i = E_i' - sum_{j
ot= i} P_jC_{j o i} + E_j
]
即考虑真实情况下可能会停在其它的地方,而我们却又将其算上了。其中 (P_j) 表示停在 (j) 的概率,(C_{j o i}) 表示在假设只有在第 (i) 个人处集齐才停止 的情况下,从全部在 (j) 到全部在 (i) 的期望步数。显然 (C_{j o i}) 对于所有的 ((j,i)) 都是一样的。
再推一下式子:
[sum E_i = E_{i}' - sum_{j
ot= i}P_jC
]
[ans = E_{i}' - sum_{j
ot= i}P_jC
]
[egin{aligned}
n imes ans &= sum_i E_i' - C(n-1)sum_jP_j\
&= sum_i E_i' - C(n-1)
end{aligned}]
现在考虑求 (E_i')。因为我们拆开考虑了,(i) 以外的人都可以看作一样的,因此可以用 (i) 有多少饼干作为状态。设 (f_i) 表示当前那个人拥有 (i) 个饼干,一直到第 (i) 个人拥有全部饼干,的期望步数。于是 (E_i' = f_{a_i}),(C_{j o i} = f_0)
考虑求解 (f_i)。枚举下一步操作选中的饼干拥有者以及传向的人的类型:(设 (sum a_i = m))
[f_i = 1 + frac{i}{m} f_{i - 1} + frac{m - i}{m} (frac{1}{n-1}f_{i+1} + frac{n-2}{n-1}f_i)
]
特别地:
[f_0 = 1 + frac{1}{n-1}f_1 + frac{n - 2}{n - 1}f_0
]
[f_m = 0
]
然后就可以高斯消元了。
然而还是太麻烦。可以用分手是祝愿(或者线性生物)的套路(好像还不太一样):考虑从 (i) 变为 (i + 1) 的期望步数,即设 (g_i = f_i - f_{i + 1})(后缀差分数组),那么就有 (f_i = sum_{j = i}^mg_j),然后继续化简:
[egin{aligned}
sum_{j = i}^mg_j &= 1 + frac{i}{m}sum_{j = i - 1}^m g_j + frac{m-i}{m}(frac{1}{n-1} sum_{j = i + 1}^m g_j + frac{n-2}{n-1}sum_{j = i}^m g_j)\
sum_{j = i}^mg_j &= 1 + frac{i}{m}sum_{j = i - 1}^m g_j + frac{m-i}{m}(sum_{j = i + 1}^m g_j + frac{n-2}{n-1}g_i)\
sum_{j = i}^mg_j &= 1 + frac{i}{m}sum_{j = i - 1}^m g_j + frac{m-i}{m}sum_{j = i + 1}^m g_j + frac{m-i}{m}frac{n-2}{n-1}g_i\
g_i &= 1 + frac{i}{m}g_{i-1} + frac{i}{m} g_i + frac{m - i}{m}frac{n - 2}{n - 1}g_i\
g_i &= (n-1)frac{m}{m-i}(1 + frac{i}{m}g_{i-1})
end{aligned}]
然后就可以直接递推了。
(Code:)
int main() {
read(n);
for (int i = 1; i <= n; ++i) read(a[i]), m += a[i];
init();
g[0] = n - 1;
for (int i = 1; i <= m; ++i)
g[i] = inv[m - i] * (1ll * m * (n - 1) % P + 1ll * i * (n - 1) % P * g[i - 1] % P) % P;
for (int i = m; ~i; --i) f[i] = (f[i + 1] + g[i]) % P;
ll S = 0;
for (int i = 1; i <= n; ++i) E_[i] = f[a[i]], S = (S + E_[i]) % P;
ll C = f[0];
ll ans = inv[n] * (S - C * (n - 1) % P) % P;
printf("%lld
", (ans % P + P) % P);
return 0;
}