生活随笔
收集整理的這篇文章主要介紹了
[bzoj2893] 集合计数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
一個有N個元素的集合有2^N 個不同子集(包含空集),現在要在這2^N個集合中取出若干集合(至少一個),使得
它們的交集的元素個數為K,求取法的方案數,答案模1000000007。(是質數喔~)
一行兩個整數N,K
Output
一行為答案。
3 2
Sample Output
6
HINT
【樣例說明】
假設原集合為{A,B,C}
則滿足條件的方案為:{AB,ABC},{AC,ABC},{BC,ABC},{AB},{AC},{BC}
【數據說明】
? 對于100%的數據,1≤N≤1000000;0≤K≤N;
題解
bzoj題目鏈接(權限題)
前置知識:廣義容斥原理
考慮對于每個方案作為一個元素,每一位相同作為一個性質。
考慮在\(n\)個里選\(x\)個,要滿足這\(x\)個性質,即集合中有\(x\)個相同,剩下\(n-x\)個集合里的元素可選可不選,但是不能都不選,要減去空集的一個,注意這里的集合指的是題目中的集合,
所以可得:
\[ \alpha (x) = \binom{n}{x} (2^{2^{n-x}}-1) \]
然后設\(\beta (x)\)為恰好有x個性質的元素個數,可得:
\[ \beta(x) = \sum _{i=x} ^{n} (-1)^{i-x}\binom{i}{x} \alpha(i) \]
答案為\(\beta (k)\)。
#include<bits/stdc++.h>
using namespace std;#define int long longvoid read(int &x) {x=0;int f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}void print(int x) {if(x<0) x=-x,putchar('-');if(!x) return ;print(x/10),putchar(x%10+'0');
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}#define maxn 1000050
#define mod 1000000007int n,fac[maxn],ifac[maxn],f[maxn],k;int qpow(int a,int x) {int res=1;for(;x;x>>=1,a=a*a%mod) if(x&1) res=res*a%mod;return res;
}signed main() {read(n),read(k);f[0]=2,fac[0]=ifac[0]=1;for(int i=1;i<=n;i++) f[i]=f[i-1]*f[i-1]%mod,fac[i]=fac[i-1]*i%mod;ifac[n]=qpow(fac[n],mod-2);for(int i=n-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;int ans=0;for(int op=-1,i=k;i<=n;i++) {op=-op;ans=(ans+op*fac[n]*ifac[i]%mod*ifac[n-i]%mod*(f[n-i]-1)%mod*fac[i]%mod*ifac[k]%mod*ifac[i-k]%mod)%mod;}write((ans%mod+mod)%mod);return 0;
}
轉載于:https://www.cnblogs.com/hbyer/p/10028522.html
總結
以上是生活随笔為你收集整理的[bzoj2893] 集合计数的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。