bzoj 2839 集合计数——二项式反演
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2839
设 \( g(i) \) 表示至少有 i 个, \( f(i) \) 表示恰好有 i 个,则
\( g(i)=C_{n}^{i}*(2^{2^{n-i}}-1) \)
\( g(i)=\sum\limits_{j=i}^{n}C_{j}^{i}f(j) \)
\( f(i)=\sum\limits_{j=i}^{n}(-1)^{j-i}C_{j}^{i}g(j) \)
以为把 g 写出来后 \( C_{n}^{i}*C_{i}^{j} = C_{n}^{j} \) ,然而其实 \( C_{n}^{i}*C_{i}^{j} = C_{n}^{j}*C_{n-j}^{i-j} \) 。
注意指数取模是 mod-1 。
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=1e6+5,mod=1e9+7; int n,k,g[N],jc[N],jcn[N]; void upd(int &x){x>=mod?x-=mod:0;x<0?x+=mod:0;} int pw(int x,int k,int md=mod) {int ret=1;while(k){if(k&1)ret=(ll)ret*x%md;x=(ll)x*x%md;k>>=1;}return ret;} void init() { jc[0]=1;for(int i=1;i<=n;i++)jc[i]=(ll)jc[i-1]*i%mod; jcn[n]=pw(jc[n],mod-2);for(int i=n-1;i>=0;i--)jcn[i]=(ll)jcn[i+1]*(i+1)%mod; } int C(int n,int m) {return (ll)jc[n]*jcn[m]%mod*jcn[n-m]%mod;} int main() { scanf("%d%d",&n,&k); init(); int ans=0; for(int i=k,j=1;i<=n;i++,j=-j) ans=(ans+(ll)j*C(i,k)*C(n,i)%mod*(pw(2,pw(2,n-i,mod-1))-1))%mod,upd(ans); printf("%d\n",ans); return 0; }