题目描述
输入格式
输出格式
样例
数据范围与提示
这题是个容斥好题
然而我蒟蒻的只能怂题解。。。。。
**********************************************
首先可以发现单纯的求满足条件的个数是不行的
可以先将K个元素提前取出
即C(n,k)*2^(2^n-k)-1为大于k个符合时的方案数
然而这会把k+1,k+2.。。。情况算是上
开始蒟蒻想用>=k的情况减>=k+1的情况
然而这是不行的
设f[k]=C(n,k)*(2^(2^n-k)-1)
在算情况k+1时假设固定k个他会由k的状态中C(k+1,k)方式算出
则-C(K+1,k)*f[k-1]
然而这样还是会多减
so还要在k+2加上
然后就愉快的容斥了.
if((i-k)&1==0)ans=(ans+f[i-k]*c(k,i))%p;
else ans=(ans-f[i-k]*c(k,i))%p;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #define MAXN 1000601 7 #define ll long long 8 using namespace std; 9 ll p=1000000007; 10 ll f[MAXN];ll sum[MAXN]; 11 ll ni[MAXN]; 12 ll N,K; 13 ll ci[MAXN]; 14 void kxx() 15 { 16 ci[0]=1; 17 for(int i=1;i<=N;++i) 18 { 19 ci[i]=(ci[i-1]<<1)%(p-1); 20 } 21 } 22 ll pow(ll x,ll y) 23 { 24 ll ans=1; 25 while(y>0) 26 { 27 if(y&1)ans=ans*x%p; 28 x=x*x%p; 29 y>>=1; 30 } 31 return ans%p; 32 } 33 ll C(ll x,ll y) 34 { 35 if(y>x)return 0; 36 //printf("ni=%lld ",ni[x-y]); 37 return (sum[x]*ni[y])%p*ni[x-y]%p; 38 } 39 void work() 40 { 41 for(ll i=K;i<=N;++i) 42 { 43 f[i]=C(N,i)*(pow(2ll,ci[N-i])-1ll); 44 f[i]%=p; 45 } 46 ll ans=0; 47 for(ll i=K;i<=N;++i) 48 { 49 if((i-K)%2==0) 50 { 51 ans=(ans+C(i,K)*f[i])%p; 52 } 53 else 54 ans=(ans-C(i,K)*f[i]+p)%p; 55 } 56 printf("%lld ",(ans+p)%p); 57 } 58 int b[MAXN]; 59 int main() 60 { 61 scanf("%lld%lld",&N,&K); 62 sum[0]=1;ni[0]=1;sum[1]=1;ni[1]=1; 63 b[0]=1;b[1]=1; 64 kxx(); 65 for(ll i=2;i<=N;++i) 66 { 67 sum[i]=(sum[i-1]*i)%p; 68 b[i]=(p-p/i)*b[p%i]%p; 69 ni[i]=ni[i-1]*b[i]%p; 70 } 71 work(); 72 }