首页 > 其他分享 >BZOJ2839/LG10596 集合计数 题解(二项式反演+扩展欧拉定理)

BZOJ2839/LG10596 集合计数 题解(二项式反演+扩展欧拉定理)

时间:2024-08-02 14:28:11浏览次数:12  
标签:反演 int 题解 个数 times BZOJ2839 choose 集合

题目大意:一个有 \(N\) 个元素的集合有 \(2^N\) 个不同子集(包含空集),现在要在这 \(2^N\) 个集合中取出若干集合(至少一个),使得它们的交集的元素个数为 \(K\),求取法的方案数,答案模 \(10^9+7\)。

为表述方便,不妨设这 \(i\) 个元素分别为 \(1\sim n\)。

前置知识:二项式反演。

考虑设 \(g(x)\) 为我们选择恰好 \(x\) 个数,要求选出若干个集合他们的交集里是这 \(x\) 个数的方案数,这个东西由于是“恰好”不好计数,考虑设 \(f(x)\) 表示说我们钦定 \(x\) 个数他一定要在这若干个集合的交集中的方案数。

\(f(x)\) 是好求的,我们直接从集合中钦定 \(x\) 个数一定要在若干个集合的交集中(其他数在不在我不关心),然后考虑包含这 \(x\) 个数的集合数量,显然除了这 \(x\) 个数必选以外,其余的数可选可不选,所以这部分的数量是 \(2^{n-x}\) 的。然后对于这些包含这 \(x\) 个数的集合,对于每个集合来说我们也是可选可不选,所以最终这部分的答案是 \({n\choose x}\times(2^{2^{n-x}}-1)\),这部分的 \(-1\) 是因为要排除掉空集。

接下来考虑如果 我们已知 \(g\),如何用 \(g\) 表示出 \(f\)(以方便我们用二项式反演从 \(f\) 反推回 \(g\)),显然\(f(x)=\sum_{i=x}^ng(i)\times{n\choose i}\),代表说我们对于每一个 \(i\ge x\),我们恰好选 \(i\) 个数的方案数之和就是钦定 \(x\) 个数的方案数。然后对这个式子用一下二项式反演:

\[f(x)=\sum_{i=x}^n{n\choose i}\times g(i)\Leftrightarrow g(x)=\sum_{i=x}^n(-1)^i\times{n\choose i}\times{i\choose x}\times(2^{2^{n-i}}-1) \]

最后用一遍扩展欧拉定理就做完了,时间复杂度 \(O(n\log n)\),如果预处理 \(2^{2^i}\) 可以做到 \(O(n)\)。

const int MAXN = 1e6 + 5, mod = 1e9 + 7;
int n, k, fac[MAXN], ifac[MAXN];

int quickpow(int a, int b, int p = mod) {
	int ret = 1;
	while (b) {
		if (b & 1) ret = ret * a % p;
		a = a * a % p; b >>= 1;
	}
	return ret;
}

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

void work() {
	cin >> n >> k;
	fac[0] = 1;
	for (int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
	ifac[n] = quickpow(fac[n], mod - 2);
	for (int i = n; i; i--) ifac[i - 1] = ifac[i] * i % mod; 
	int ans = 0, coff = 1;
	for (int i = k; i <= n; ++i) {
		ans = ans + coff * C(i, k) * C(n, i) % mod * quickpow(2, quickpow(2, n - i, mod - 1)) % mod;
		ans = (ans % mod + mod) % mod;
		coff = -coff;
	}
	cout << ans << endl;
}

标签:反演,int,题解,个数,times,BZOJ2839,choose,集合
From: https://www.cnblogs.com/XiaoQuQu/p/18338704

相关文章

  • 题解:CF1537E2 Erase and Extend (Hard Version)
    CF1537E2EraseandExtend题解分析通过观察题目,可以证明结果一定是由多次前缀复制得来的。题目要求你进行删和复制的操作,与其交替着操作,不如直接先删到最优的前缀再进行复制。现在就是要找最优的前缀。从头一位一位往后遍历。用\(l\)来存储目前最优前缀的长度,第\(i\)位......
  • 题解:CF1301B Motarack's Birthday
    CF1301DTimetoRun题解思维题。分析把一个格子视作一个点,每个点的度数都是偶数,所以这是一张欧拉图。而需要走遍整个方格图,可以证明只要\(k\)不超过\(4nm-2n-2m\)就一定有解。很明显存在很多种方案,这里我用的方案是:从左上角出发,向右走\(m-1\)步到头,再向左走\(m-1\)......
  • 题解:CF634A Island Puzzle
    CF634AIslandPuzzle题解分析由于我们仅能移动\(0\),所以其它数字的相对顺序较原来应该是不变的,所以我们从环中删除\(0\)再判断相对位置即可。还有需要注意的是本题是一个环,找到末尾需要用取模操作回到开头继续比较。示例代码#include<bits/stdc++.h>usingnamespacest......
  • 题解:CF718A Efim and Strange Grade
    CF718AEfimandStrangeGrade题解算法贪心+模拟思路分析显然,要最优每一次进位就只能五入不能四舍。而且当我们五入时,要取位数最高的。比如说\(1.3535\),我们有两种进位方式,一种是进位成\(1.4\),一种是进位成\(1.354\),显然前者更优。那这道题给的次数有啥用呢?考虑一种“......
  • 题解:CF1301D Time to Run
    CF1301DTimetoRun题解思维题。分析把一个格子视作一个点,每个点的度数都是偶数,所以这是一张欧拉图。而需要走遍整个方格图,可以证明只要\(k\)不超过\(4nm-2n-2m\)就一定有解。很明显存在很多种方案,这里我用的方案是:从左上角出发,向右走\(m-1\)步到头,再向左走\(m-1\)......
  • 题解:CF771A Bear and Friendship Condition
    CF771ABearandFriendshipCondition题解算法并查集,图的基本性质分析题目意思是,一旦有一些点联通,那么这些点必须两两直接相连。换句话讲,就是图中的每个联通块都是完全图。所谓完全图,就是图中的每个点都两两相连,假设一个完全图有\(n\)个点,那么我们可以通过乘法原理算出这......
  • 题解:CF507C Guess Your Way Out!
    CF507CGuessYourWayOut!题解算法模拟思路按照左右左右的方式先往下找,每次找到一个子节点时就看此节点为根的子树是否包含目标节点,如果包含就继续往下走,不包含说明目标叶子节点在另一边的子树上,那么肯定是先需要把这边的子树遍历完才能换到另一边,所以答案直接加上这个子树......
  • HT-018 Div3 构造 题解 [ 黄 ] [ 数学 ] [ 结论 ]
    构造:结论题,gcy数竞大佬tql%%%orz。结论先放结论:如果\(x\bmod4=2\),那么\(x\)无法被表示为\(a^2-b^2\)的形式;除此之外的其他数都可以。证明对\(a^2-b^2\)因式分解,得\(x=(a+b)(a-b)\)。当\(x\bmod2=1\)时包含\(x\bmod4=1\)和\(x\bmod4=3\)的情况。......
  • Educational Codeforces Round 168 (Rated for Div. 2)A——D题解
    EducationalCodeforcesRound168(RatedforDiv.2)A——D题解A.StrongPassword题意:给一个小写字符串密码,添加一个小写字母,使得密码更加复杂。题解:有相同的相邻的字母,再其中间添加不同的字母;如果没有相同的相邻的字母,则最后添加一个字母。#include<bits/stdc++.h>......
  • HT-018 Div3 能量消耗 题解 [ 绿 ] [ 线性 dp ] [ 前缀和优化 ]
    能量消耗:一个前缀和优化dp的大典题,要是数据水一点\(O(n^3)\)都能硬草过去。思路显然,定义\(dp[i]\)为考虑前\(i\)个塔,并且将前面的精灵全部收集的最小代价。于是转移:\[dp[i]=min(dp[i],dp[j]+w(j,i)+c[i])\]其中\(0\lej<i\lem\),\(w(j,i)\)表示收集从塔\(j\)到......