CF1349D Slime and Biscuits
考虑停在每个人的贡献。设 \(E_i\) 表示最终停在第 \(i\) 个人的 概率 \(\times\) 步数 之和,那么 \(Ans = \sum_{i}E_i\)。但是 \(E_i\) 仍然不好算,因为中间可能突然停到了另一个人上。于是我们设 \(E_i'\) 表示假设只有在第 \(i\) 个人处集齐才停止的期望步数,那么就可以用类似随机游走的模型来方便地搞了。
考虑 \(E\) 和 \(E'\) 的关系:
即考虑真实情况下可能会停在其它的地方,而我们却又将其算上了。其中 \(P_j\) 表示停在 \(j\) 的概率,\(C_{j \to i}\) 表示在假设只有在第 \(i\) 个人处集齐才停止 的情况下,从全部在 \(j\) 到全部在 \(i\) 的期望步数。显然 \(C_{j \to i}\) 对于所有的 \((j,i)\) 都是一样的。
再推一下式子:
现在考虑求 \(E_i'\)。因为我们拆开考虑了,\(i\) 以外的人都可以看作一样的,因此可以用 \(i\) 有多少饼干作为状态。设 \(f_i\) 表示当前那个人拥有 \(i\) 个饼干,一直到第 \(i\) 个人拥有全部饼干,的期望步数。于是 \(E_i' = f_{a_i}\),\(C_{j \to i} = f_0\)
考虑求解 \(f_i\)。枚举下一步操作选中的饼干拥有者以及传向的人的类型:(设 \(\sum a_i = m\))
特别地:
然后就可以高斯消元了。
然而还是太麻烦。可以用分手是祝愿(或者线性生物)的套路(好像还不太一样):考虑从 \(i\) 变为 \(i + 1\) 的期望步数,即设 \(g_i = f_i - f_{i + 1}\)(后缀差分数组),那么就有 \(f_i = \sum_{j = i}^mg_j\),然后继续化简:
然后就可以直接递推了。
\(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\n", (ans % P + P) % P);
return 0;
}