BZOJ2839 : 集合计数 (广义容斥定理)

题目

一个有 N 个 元素的集合有 2N 个不同子集(包含空集),

现在要在这 2N 个集合中取出若干集合(至少一个),

使得它们的交集的元素个数为 K ,求取法的方案数,答案模 1000000007

(1N106,0KN)

题解

又是一道 裸的 广义容斥定理 还没这道题难qwq

广义容斥定理 (二项式反演) :

bk=i=kn(ik)ai

ak=i=kn(1)ik(ik)bi

不难发现又是一个恰好 我们转化成至少就行了

那么交集有至少 i 个集合的个数 bi 就是

bi=(ni)22ni

一开始我以为后面那个直接是 2ni .... 没过样例搜了波题解... 发现是 22ni qwq

为什么呢 我们这样考虑 当前枚举了一个大小为 i 交集后 还剩下 ni 个元素

每个元素有选和不选的两种方案 那么共有 2ni 个互不相同的集合

那么每个集合我们又有选和不选两种方案 那么总共就是 22ni 种咯qwq

然后套上去 答案就是

ans=i=kn(1)ik(ik)bi

代码

#include <bits/stdc++.h> #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i) #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i) #define Set(a, v) memset(a, v, sizeof(a)) using namespace std; inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;} inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;} inline int read() { int x = 0, fh = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1; for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48); return x * fh; } void File() { #ifdef zjp_shadow freopen ("P2839.in", "r", stdin); freopen ("P2839.out", "w", stdout); #endif } typedef long long ll; const ll Mod = 1e9 + 7; ll fpm(ll x, int power) { ll res = 1; for (; power; power >>= 1, (x *= x) %= Mod) if (power & 1) (res *= x) %= Mod; return res; } const int N = 1e6; ll fac[N + 100], ifac[N + 100], pow2[N + 100], ppow2[N + 100]; void Init(int maxn) { fac[0] = ifac[0] = pow2[0] = ppow2[0] = 1; For (i, 1, maxn) fac[i] = fac[i - 1] * i % Mod, pow2[i] = pow2[i - 1] * 2 % Mod, ppow2[i] = ppow2[i - 1] * 2 % (Mod - 1); ifac[maxn] = fpm(fac[maxn], Mod - 2); Fordown (i, maxn - 1, 1) ifac[i] = ifac[i + 1] * (i + 1) % Mod; } ll ans = 0; ll C(int n, int m) { if (n < 0 || m < 0 || n < m) return 0; return fac[n] * ifac[m] % Mod * ifac[n - m] % Mod; } int main () { File(); Init(N); int n = read(), k = read(); For (i, k, n) (ans += Mod + ((i - k) & 1 ? -1 : 1) * (C(i, k) * C(n, i) % Mod * fpm(2, ppow2[n - i]) % Mod)) %= Mod; printf ("%lld\n", ans); return 0; }

__EOF__

本文作者zjp_shadow
本文链接https://www.cnblogs.com/zjp-shadow/p/8719430.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zjp_shadow  阅读(1014)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示