← 全部文章

ARC096E Everything on It 题解

本文目录(3 节)
  1. 题意
  2. 题解
  3. 代码

ARC096E Everything on It

题意

  • 有一个包含 nn 个元素的集合 SS。
  • 你要选择若干个互不相同的 SS 的子集,使得每个元素至少出现两次,求方案数。
  • n≤3×103n \le 3 \times 10^3,答案对 MM 取模。

题解

考虑容斥,设 f(i)f(i) 表示有至少 ii 个数出现了最多一次,则答案为 ∑i=0n(−1)i(ni)f(i)\sum_{i=0}^n (-1)^i\binom ni f(i)。

枚举这 ii 个数被划分到 jj 个集合中。由于可能有一些数没有出现过,因此我们可以新增一个数 00,将这 i+1i+1 个数划分到 j+1j+1 个集合中,与 00 在同一集合的数没有出现过,这部分方案数为 S2(i+1,j+1)S_2(i+1, j+1)。

考虑剩下 n−in-i 个数,首先存在 2n−i2^{n-i} 个集合可选可不选,方案数为 22n−i2^{2^{n-i}},然后之前的 jj 个中每个集合又可以与这 2n−i2^{n-i} 个集合并起来,方案数为 (2n−i)j(2^{n-i})^j。

因此 f(i)=∑j=0iS2(i+1,j+1)⋅22n−i⋅(2n−i)jf(i) = \sum_{j=0}^i S_2(i+1,j+1) \cdot 2^{2^{n-i}} \cdot (2^{n-i})^j,最终的答案可以 O(n2)\mathcal O(n^2) 计算。

代码

const int N = 3e3 + 7;
int n;
modint s[N][N], ans;

inline modint f(int i) {
	modint w = (modint)2 ^ (n - i), o = 1, ret = 0;
	for (int j = 0; j <= i; j++, o *= w)
		ret += s[i+1][j+1] * o;
	--P, w = (modint)2 ^ (n - i), ++P;
	return ret * ((modint)2 ^ w.x);
}

int main() {
	rd(n, P);
	init(n);
	s[0][0] = 1;
	for (int i = 1; i <= n + 1; i++)
		for (int j = 0; j <= i; j++)
			s[i][j] = (j ? s[i-1][j-1] : 0) + j * s[i-1][j];
	for (int i = 0; i <= n; i++)
		if (i & 1) ans -= binom(n, i) * f(i);
		else ans += binom(n, i) * f(i);
	print(ans);
	return 0;
}

标签:容斥、组合计数

评论

    填写昵称即可留言。评论经站主审核后公开,请勿提交私人信息。

    正在连接评论服务…