# [bzoj2339][HNOI2011]卡农——动态规划+容斥原理

### 思路：

$2^n-1$个片段中选择$m-1$个的方案为${2^n-1\choose m-1}$

#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define MREP(i,x) for(int i=beg[x],v;v=to[i],i;i=las[i])
#define debug(x) cout<<#x<<"="<<x<<endl
#define fi first
#define se second
#define mk make_pair
#define pb push_back
typedef long long ll;

using namespace std;

void File(){
freopen("bzoj2339.in","r",stdin);
freopen("bzoj2339.out","w",stdout);
}

T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}

const int maxn=1e6+10;
const ll mod=1e8+7;
int n,m;
ll p2,fac[maxn],f[maxn];

ll qpow(ll x,ll y){
ll ret=1; x%=mod;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;
y>>=1;
}
return ret;
}

int main(){
//File();

p2=(qpow(2,n)-1)%mod;

fac[0]=1;
REP(i,1,m)fac[i]=fac[i-1]*(p2-i+1)%mod;

f[0]=1,f[1]=0;
REP(i,2,m){
f[i]=fac[i-1];
f[i]=(f[i]-f[i-1])%mod;
f[i]=(f[i]-(i-1)*f[i-2]%mod*(p2-i+2)%mod)%mod;
}

ll tmp=1;
REP(i,1,m)tmp=tmp*i%mod;

f[m]=f[m]*qpow(tmp,mod-2)%mod;

printf("%lld\n",(f[m]+mod)%mod);

return 0;
}

posted @ 2018-12-12 19:00  ylsoi  阅读(135)  评论(0编辑  收藏  举报