Lust 题解
很好的一道 EGF 入门题。
我们发现每一操作一次,答案增加多少,\(\prod a_i\) 就减小多少。
于是答案即为 \(\prod a_i-\prod (a_i-b_i)\),其中 \(b_i\) 为在 \(i\) 位子上操作的次数。
显然我们只需算出后面这坨的期望就行了,前面是固定的。
期望是困难的,先化为普通式子。
\[\begin{align*}
& \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!}
\end{align*}
\]
注意求和的那坨式子,看到 \(\sum b_i=k\) 在条件上就想 \(\cdots\) 嗯,生成函数。
说来就来,写出 :
\[\hat F(x) = \sum_{i=0}^\infty \left(\sum_{\sum b_j = i}\prod \cfrac{a_j-b_j}{b_j!}\right)x^i
\]
再把求和后面那一坨拎出来:
\[\begin{align*}
&\hat G_i(x)\\
=& \sum_{j=0}^\infty \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
\end{align*}
\]
发现 \(\hat F\) 就是 \(\hat G\) 的加法和卷积,所以:
\[\begin{align*}
& \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!}
\end{align*}
\]
左边这个求积的各项系数显然可以求出(方法放在后面),设其为 \(H(x)=\sum h_ix^i\)。
所以答案即为:
\[\begin{align*}
&\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}
\end{align*}
\]
这里就做完了。
现在我们回过头来想怎么求出 \(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;
}