ABC215G

首先先把颜色都离散化。

\(f\) 为所求答案,那么对于 \(f(1)\sim f(n)\) 分别计算其期望。因为期望的线性性,分别考虑每种颜色被选中至少一个的概率(因为每种颜色对答案的贡献是 \(1\) 所以期望就等于概率)。

设有 \(m\) 种不同颜色,第 \(i\) 种颜色出现次数为 \(cnt_i\),则有:

\[f(k)=\sum_{i=1}^{m}\dfrac{\dbinom{n}{k}-\dbinom{n-cnt_i}{k}}{\dbinom{n}{k}} \]

显然过不去,但是发现对于出现次数一样的颜色,它们的贡献也一样。

于是设 \(g(i)\) 表示出现次数为 \(i\) 的颜色个数。那么原式变成:

\[f(k)=\sum_{i=1}^{n}g(i)\dfrac{\dbinom{n}{k}-\dbinom{n-i}{k}}{\dbinom{n}{k}} \]

经典结论,\(g(i)\ne0\) 的个数是 \(\mathcal O(\sqrt n)\) 的。

于是总复杂度 \(\mathcal O(n\sqrt n)\)

Code:

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef pair <int, int> pii;
const int N = 50005, mod = 998244353;
int n;
int a[N], b[N], cnt;
int fac[N], inv[N];
int sum[N], num[N];
vector <pii> vec;

int qpow(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1) res = 1ll * res * x % mod;
		x = 1ll * x * x % mod;
		y >>= 1;
	}
	return res;
}

void init(int maxn) {
	fac[0] = 1;
	for (int i = 1; i <= maxn; ++i) fac[i] = 1ll * fac[i - 1] * i % mod;
	inv[maxn] = qpow(fac[maxn], mod - 2);
	for (int i = maxn - 1; ~i; --i) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
}

int C(int n, int m) {
	if (n < 0 || m < 0 || n < m) return 0;
	return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod;
}

void add(int &a, int b) {
	a += b;
	if (a >= mod) a -= mod;
}

int main() {
	scanf("%d", &n); init(n);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
		b[++cnt] = a[i];
	}
	sort(b + 1, b + cnt + 1); cnt = unique(b + 1, b + cnt + 1) - (b + 1);
	for (int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + cnt + 1, a[i]) - b, ++sum[a[i]];
	for (int i = 1; i <= cnt; ++i) ++num[sum[i]];
	for (int i = 1; i <= n; ++i) if (num[i]) vec.pb(pii(i, num[i]));
	for (int k = 1; k <= n; ++k) {
		int ans = 0;
		for (auto tmp : vec) add(ans, 1ll * tmp.se * ((C(n, k) - C(n - tmp.fi, k) + mod) % mod) % mod);
		ans = 1ll * ans * qpow(C(n, k), mod - 2) % mod;
		printf("%d\n", ans);
	}
	return 0;
}
posted @ 2022-11-07 20:25  Kobe303  阅读(18)  评论(0编辑  收藏  举报