CF1349D Slime and Biscuits

题目链接

考虑停在每个人的贡献。设 (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;
}

另解

原文地址:https://www.cnblogs.com/JiaZP/p/13722793.html