ABC231G
先来研究没有初始球情况下的简单版本:
\(n\) 个小球,\(m\) 个盒子,每个小球等概率地放到盒子里,这样有 \(n^m\) 种方案,每种方案的贡献是每个盒中球个数的乘积,计算所有方案贡献总和。
设 \(x_{i.j}\) 表示第 \(i\) 个盒子中是否放入了第 \(j\) 个球,取值只有 \(0\) 或者 \(1\)。
对于一种具体的方案来说,贡献为:
展开后,一共有 \(m^n\) 项,每项为 \(x_{1,t_1}x_{2,t_2}\cdots x_{n,t_n}\),如果该项有贡献则说明 \(t_i\) 互不相同且 \(x_{i,t_i}=1\),则有 \(m\times(m-1)\times\cdots\times (m-n+1)=\dfrac{m!}{(m-n)!}\) 种确定 \(\left\{t_i\right\}\) 的方案,因为剩下的球随便放,所以方案数是 \(n^{m-n}\)。于是总贡献为 \(\dfrac{m!}{(m-n)!}\times n^{m-n}\)。
再回到原问题,设每个盒子的增量是 \(b_i\),满足 \(\sum b_i=m\),那么总贡献为:
展开后,一共有 \(2^n\) 项,每项由 \(x\) 个 \(a_i\) 的乘积和 \(n-x\) 个 \(b_i\) 的乘积组成。
于是可以将 \(a\) 的乘积直接 DP 出来,设 \(f_{i,j}\) 表示前 \(i\) 个数,选出 \(j\) 个的乘积和,则有:
则最终答案可以写成 \(\sum\limits_{x=0}^nf_{n,x}\times \sum\limits_{\left\{b_i\right\}}\prod b_k=\sum\limits_{x=0}^nf_{n,x}\times g_{n-x}\),其中 \(g_{n-x}\) 表示合法的 \(n-x\) 项 \(b_k\) 的乘积和。
而 \(g_i\) 就是上面的简化版本,\(g_i=\dfrac{m!}{(m-i)!}\times n^{m-i}\)。
最后用总贡献除以 \(n^m\) 就是题目所求的期望。
时间复杂度 \(\mathcal O(n^2)\)。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005, mod = 998244353;
int n, m;
int a[N];
int f[N][N], g[N];
int qpow(int x, int y) {
if (y < 0) return 0;
int res = 1;
while (y) {
if (y & 1) res = 1ll * res * x % mod;
x = 1ll * x * x % mod;
y >>= 1;
}
return res;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
f[i][0] = 1;
for (int j = 1; j <= i; ++j)
f[i][j] = (f[i - 1][j] + 1ll * f[i - 1][j - 1] * a[i] % mod) % mod;
}
int cur = 1;
g[0] = qpow(n, m);
for (int i = 1; i <= n; ++i) {
cur = 1ll * cur * (m - i + 1) % mod;
g[i] = 1ll * cur * qpow(n, m - i) % mod;
}
int ans = 0;
for (int i = 0; i <= n; ++i) ans = (ans + 1ll * f[n][i] * g[n - i] % mod) % mod;
ans = 1ll * ans * qpow(qpow(n, m), mod - 2) % mod;
printf("%d", ans);
return 0;
}