[容斥原理] BZOJ 2839 集合计数

来源:互联网 发布:招聘网络平面设计师 编辑:程序博客网 时间:2024/05/04 18:29

考虑容斥原理 计算交集大小至少为i的集合有多少种
首先需要选出i个元素 方案为Cin
其它2ni个集合每个可选可不选 一共22ni1
故答案为

i=kn(1)ikCinCki(22ni1)

#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;const int N=1e6+5;const int P=1e9+7;inline ll Pow(ll a,int b,int P=::P){  int res=1;  for (;b;b>>=1,a=1ll*a*a%P) if (b&1) res=1ll*res*a%P;  return res;}ll fac[N],inv[N];inline void Pre(int n){  fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%P;  inv[1]=1; for (int i=2;i<=n;i++) inv[i]=inv[P%i]*(P-P/i)%P;  inv[0]=1; for (int i=1;i<=n;i++) inv[i]=inv[i]*inv[i-1]%P;}inline ll C(int n,int m){  return fac[n]*inv[m]%P*inv[n-m]%P;}int main(){  ll Ans=0,tmp,n,K;  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  scanf("%lld%lld",&n,&K); Pre(n);  for (int i=K;i<=n;i++){    tmp=C(i,K)*C(n,i)%P*((Pow(2,Pow(2,n-i,P-1))+P-1)%P)%P;    if ((i-K)&1) Ans+=P-tmp;    else Ans+=tmp;  }  printf("%lld\n",Ans%P);  return 0;}
0 0