CF891E

生成函数

题意翻译

你有 \(n\) 个数 \(a_1,a_2,…,a_n\)​ 要进行 \(k\) 次操作,每次随机选择一个数 \(x \in [1,n]\),把 \(a_x\)​ 减一,并将答案增加除 \(a_i\) 外所有数的乘积。

求最终答案的期望,答案对 \(10^9 + 7\) 取模。

解法

设当前选择 \(a_x\) 贡献为

\[\prod_{i \ne x} a_i = \prod a_i - (a_x - 1) \prod_{i \ne x} a_x \]

发现是两个序列乘积的差,递推到最后一次操作,我们只需要知道最终每个 \(a_i\) 减了多少 \(b_i\) 即可,也就是求

\[E(\prod a_i - \prod (a_i - b_i)) \]

\[= \prod a_i - E(\prod (a_i - b_i)) \]

转换为求方案的和

\[= \prod a_i - \frac 1 {n ^ k} \sum_{\sum b_i = k} \frac {k!} {\prod {b_i !}} \prod (a_i - b_i) \]

\[= \prod a_i - \frac {k!} {n ^ k} \sum_{\sum b_i = k} \prod \frac {(a_i - b_i)} {b_i!} \]

因为 \(\sum {b_i} = k\) 联想指数运算,把它写成生成函数的样子

\[= \prod a_i - \frac {k!} {n ^ k} [x^k] \prod \sum_{j = 0} ^ \infty \frac {a_i - j} {j!} \]

考虑 \(e^{ax} = \sum_{i = 0} ^ \infty \frac {(ax)^i} {i!} x^i\) 想办法把它整成 \(e\)

\[\frac {k!} {n ^ k} [x^k] \prod \sum_{j = 0} ^ \infty \frac {a_i - j} {j!} \]

\[= \frac {k!} {n ^ k} [x^k] \prod (\sum_{j = 0} ^ \infty a_i \frac {1} {j!} x^j - x \sum_{j = 1} ^ \infty \frac {1} {(j - 1)!} x^{j - 1}) \]

\[= \frac {k!} {n ^ k} [x^k] \prod (\sum_{j = 0} ^ \infty a_i \frac {1} {j!} x^j - x \sum_{j = 1} ^ \infty \frac {1} {(j - 1)!} x^{j}) \]

\[= \frac{k!} {n ^ k} [x^k] \prod( \sum_{j = 0} ^ \infty a_i \frac {1} {j!} x^j - x \sum_{j = 0} ^ \infty \frac {1} {j!} x^{j} ) \]

\[= \frac {k!} {n ^ k} [x^k] \prod e^x (a_i - x) \]

\[= \frac {k!} {n ^ k} [x^k] e^{nx} \prod (a_i - x) \]

\[= \frac {k!} {n ^ k} [x^k] \sum_{j = 0} ^ \infty \frac {n ^ j x^j} {j!} \prod (a_i - x) \]

\(\prod_{i = 1} ^ n (a_i - x)\) 这个多项式求出来,设它的每一项系数为 \(c_i\),原式变成

\[\frac {k!} {n ^ k} \sum_{j = 0} ^ {min(n, k)} \frac {c_j n^{k - j} } {(k - j)!} \]

\[=\sum_{j = 0} ^ {min(n, k)} \frac {c_j k ^ {\underline j}} {n ^ j} \]

\(O(n^2)\) 暴力求就行了

#include <bits/stdc++.h>
using namespace std;
#define gc getchar
#define rg register
#define I inline
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define per(i, a, b) for(int i = a; i >= b; --i)
I int read(){
	rg char ch = gc();
	rg int x = 0, f = 0;
	while(!isdigit(ch)) f |= (ch == '-'), ch = gc();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
	return f ? -x : x;
}
const int mod = 1e9 + 7, N = 5005;
int sa, a[N], k, c[N], fac[N];
I int ksm(int a, int b){
	int ans = 1; 
	while(b){ if(b & 1) ans = 1ll * ans * a % mod; b >>= 1; a = 1ll * a * a % mod; }
	return ans;
}
int n;
signed main(){
	n = read(), k = read();
	fac[0] = sa = 1;
	rep(i, 1, n) fac[i] = a[i] = read(), sa = 1ll * sa * a[i] % mod;
	c[0] = a[1]; c[1] = mod - 1;
	rep(i, 2, n){
		per(j, i, 1) c[j] = (1ll * c[j] * a[i] % mod + mod - c[j - 1]) % mod;
		c[0] = 1ll * c[0] * a[i] % mod;
	}
	rep(i, 1, n) fac[i] = 1ll * fac[i - 1] * (k - i + 1) % mod;
	rep(i, 0, min(n, k)) sa = (sa + mod - 1ll * c[i] * fac[i] % mod * ksm(ksm(n, i), mod - 2) % mod) % mod;
	cout << sa << endl;
	return 0;
}
posted @ 2020-06-06 19:59  __int256  阅读(93)  评论(0编辑  收藏  举报