CF446E
很好的一道 EGF 入门题。
我们发现每一操作一次,答案增加多少,\(\prod a_i\) 就减小多少。
于是答案即为 \(\prod a_i-\prod (a_i-b_i)\),其中 \(b_i\) 为在 \(i\) 位子上操作的次数。
显然我们只需算出后面这坨的期望就行了,前面是固定的。
期望是困难的,先化为普通式子。
\[\mathbb E\left[\prod \left(a_i - b_i\right)\right]=\cfrac{1}{n^k}\sum_{\sum b_i=k} \cfrac{k!}{\prod b_i!}\prod\left(a_i-b_i\right)=\cfrac{k!}{n^k}\sum_{\sum b_i = k}\prod \cfrac{a_i-b_i}{b_i!}
\]
注意求和的那坨式子,看到 \(\sum b_i=k\) 在条件上就想 \(\cdots\) 嗯,生成函数。
说来就来,写出 :
\[\hat F(x) = \sum_{i=0}^\infin \left(\sum_{\sum b_j = i}\prod \cfrac{a_j-b_j}{b_j!}\right)x^i
\]
再把求和后面那一坨拎出来:
\[\hat G_i(x) = \sum_{j=0}^\infin \cfrac{a_i - j}{j!}x^j = \sum \cfrac{a_i}{j!}x^j - \sum\cfrac{1}{\left(j - 1\right)!}x^j=a_ie^x-x\sum \cfrac{1}{\left(j - 1\right)!}x^{j-1}=(a_i-x)e^x
\]
发现 \(\hat F\) 就是 \(\hat G\) 的加法和卷积,所以:
\[\hat F(x) = \prod \hat G_i(x) = \prod\left(a_i-x\right)e^x=e^{nx}\prod \left(a_i-x\right)=\left[\prod\left(a_i-x\right)\right]\sum \cfrac{x^in^i}{i!}
\]
左边这个求积的各项系数显然可以求出(方法放在后面),设其为 \(H(x)=\sum h_ix^i\)。
所以答案即为:
\[\mathbb E\left(ans\right) = \prod a_i - \cfrac{k!}{n^k} \left[x^k\right]\hat F(x) = \prod a_i -\sum \cfrac{h_in^{k-i}}{\left(k - i\right)!}=\prod a_i - \sum \cfrac{h_ik!}{\left(k - i\right)!n^i}
\]
这里就做完了。
现在我们回过头来想怎么求出 \(h_i\)。
我们想的是 \(\prod_{i=0}^n \left(a_i-x\right)\) 的系数,但是我们可以从 \(\prod_{i=0}^{n-1} \left(a_i-x\right)\) 的系数推出,只需要给每个位置项都乘上 \((a_n-x)\) 再更新到系数上就行了。
以此类推,只要从 \(n=0\) 的情况不断递推即可。
代码还是相当好写的。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
constexpr int MAXN = 5005;
constexpr int MOD = 1e9 + 7;
int qpow(int x, int y) {int ans = 1;while (y) {if (y & 1)ans = ans * x % MOD;x = x * x % MOD;y >>= 1;}return ans;
}
int a, n, k, c[MAXN];
signed main() {cin >> n >> k;c[0] = 1;rep (i, 1, n) {cin >> a;per (j, i, 1) {c[j] *= a;c[j] -= c[j - 1];c[j] = (c[j] + MOD) % MOD;}(c[0] *= a) %= MOD;}int ans = c[0], pw = 1;rep (i, 0, n) {(ans += MOD - pw * c[i] % MOD) %= MOD;(pw *= (k - i) * qpow(n, MOD - 2) % MOD) %= MOD;}cout << ans << endl;return 0;
}