集合计数
我想的容斥和题解不太一样
我也是想先在n个里确定K个
然后设 $$f_i=C_n^i*\sum_{p=0}^{n-i} $$
$$ ans=f_K-f_{K+1}+f_{K+2}... $$
然而这个并不对,3 2 的样例 算$f_k$的时候就已经是6了
正解:
$$ ans=C_n^K*( C_{n-K}^0*2^{2^{n-K}}-C_{n-K}^1*2^{2^{n-K-1}}... ) $$
解释:
先枚举确定n个里面的K个
在枚举另外 n-K 个元素里有几个是在交集里被选上了
$2^{2^{i}}$意思是 有i个元素剩余,子集有$2^i$个,在这些子集里再选
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <algorithm> #include <cmath> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int N=1000006; const int mod=1000000007; int ou(int x) { int tt=x,q1=sqrt(x); for(int i=2;i<=q1;++i) if(x%i==0) { tt=tt-tt/i; while(x%i==0) x/=i; } if(x!=1) tt=tt-tt/x; return tt; } ll qpow(ll a,int ci,int mm) { ll ans=1; while(ci) { if(ci&1) ans=ans*a%mm; a=a*a%mm; ci>>=1; } return ans; } int n,K; ll mi[N],mi2[N]; ll jie[N],jieni[N]; void chu() { int mod2=ou(mod); mi[0]=1; for(int i=1;i<=n;++i) mi[i]=mi[i-1]*2%mod2; for(int i=0;i<=n;++i) mi2[i]=qpow(2,mi[i],mod); jie[0]=1; for(int i=1;i<N;++i) jie[i]=jie[i-1]*i%mod; jieni[N-1]=qpow(jie[N-1],mod-2,mod)%mod; for(int i=N-2;i>=1;--i) jieni[i]=jieni[i+1]*(i+1)%mod; jieni[0]=1; } ll C(int n,int m) { if( n<0||m<0||n<m ) return 0; return jie[n]*jieni[m]%mod*jieni[n-m]%mod; } ll work() { ll ans=0,tt; int q1=n-K; for(int i=0;i<=q1;++i) { tt=C(n-K,i)*mi2[n-K-i]%mod; //printf("i=%d tt=%lld\n",i,tt); if(i&1) ans=(ans-tt+mod)%mod; else ans=(ans+tt)%mod; } return ans*C(n,K)%mod; } int main(){ scanf("%d%d",&n,&K); chu(); cout<<work(); }