zoukankan      html  css  js  c++  java
  • 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;
    }
    

    另解

  • 相关阅读:
    Windows下使用nmake编译C/C++的makefile
    poj 1228
    poj 1039
    poj 1410
    poj 3304
    poj 1113
    poj 2074
    uva 1423 LA 4255
    poj 1584
    poj 3277
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13722793.html
Copyright © 2011-2022 走看看