首页 > 其他分享 >ABC231G

ABC231G

时间:2022-11-09 13:11:42浏览次数:40  
标签:乘积 int res sum times cdots ABC231G

先来研究没有初始球情况下的简单版本:

\(n\) 个小球,\(m\) 个盒子,每个小球等概率地放到盒子里,这样有 \(n^m\) 种方案,每种方案的贡献是每个盒中球个数的乘积,计算所有方案贡献总和。

设 \(x_{i.j}\) 表示第 \(i\) 个盒子中是否放入了第 \(j\) 个球,取值只有 \(0\) 或者 \(1\)。

对于一种具体的方案来说,贡献为:

\[(x_{1,1}+x_{1,2}+\cdots+x_{1,m})(x_{2,1}+x_{2,2}+\cdots+x_{2,m})\cdots(x_{n,1}+x_{n,2}+\cdots+x_{n,m}) \]

展开后,一共有 \(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\),那么总贡献为:

\[\sum\limits_{\left\{b_i\right\}}(a_1+b_1)(a_2+b_2)\cdots(a_n+b_n) \]

展开后,一共有 \(2^n\) 项,每项由 \(x\) 个 \(a_i\) 的乘积和 \(n-x\) 个 \(b_i\) 的乘积组成。

于是可以将 \(a\) 的乘积直接 DP 出来,设 \(f_{i,j}\) 表示前 \(i\) 个数,选出 \(j\) 个的乘积和,则有:

\[f_{i,j}=f_{i-1,j}+f_{i-1,j-1}\times a_i \]

则最终答案可以写成 \(\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;
}

标签:乘积,int,res,sum,times,cdots,ABC231G
From: https://www.cnblogs.com/Kobe303/p/16873263.html

相关文章