Bzoj2839 集合计数
Posted al-ca
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj2839 集合计数相关的知识,希望对你有一定的参考价值。
C. 集合计数
题目描述
输入格式
输出格式
样例
数据范围与提示
ab%c!=ab%c!!!卡了我好久。
这道题要用到组合数和容斥,因为交集为k的方案并不好求,但是交集至少为k的方案数比较好求,所以考虑容斥:
设提前选出来k个数,然后求交集至少为k+x时的方案数:(2^ 2(n-k-x)-1)*C(n-k,x),交集至少为k+x时,有2(n-k-x)个集合,则有2^ 2(n-k-x)种方案,但是要减去一个都不选的一种,乘C(n-k,x),然后容斥,对于x奇减偶加;
但是因为k是提前选出来的,以上并没有考虑k的方案,所以最后答案*C(n,k);
错误示范:
1 LL ans=0; 2 for(int i=0;i<=n-k;i++) 3 4 LL res=(inv(2,inv(2,n-k-i))-1)*C(n-k,i)%mod; 5 if(i%2)ans-=res; 6 else ans+=res; 7 ans%=mod; 8
ab%c!=ab%c!!!但是如果把循环顺序改一下,可以发现其实inv(2,inv(2,n-k-i))是每次平方的(inv为快速幂):
#include<iostream> #include<cstdio> #define mod 1000000007 #define LL long long using namespace std; int n,k; LL jc[1000010]; LL inv(LL a,LL b) LL ans=1; while(b) if(b&1)ans=ans*a%mod; a=a*a%mod; b=b>>1; return ans%mod; LL C(LL n,LL m) if(!m)return 1; return jc[n] * inv(jc[m],mod-2) %mod * inv(jc[n-m],mod-2) %mod; void init() jc[0]=1; for(int i=1;i<=n;i++)jc[i]=jc[i-1]*i%mod; signed main() // freopen("in.txt","r",stdin); cin>>n>>k;init(); LL ans=0,pf=2; for(int i=n-k;i>=0;i--) LL res=(pf-1)*C(n-k,i)%mod; pf=pf*pf%mod; if(i%2)ans-=res; else ans+=res; ans=(ans%mod+mod)%mod; ans=(ans%mod+mod)%mod; ans=ans*C(n,k)%mod; cout<<(ans%mod+mod)%mod<<endl;
以上是关于Bzoj2839 集合计数的主要内容,如果未能解决你的问题,请参考以下文章