# ●BZOJ 2839 集合计数

http://www.lydsy.com/JudgeOnline/problem.php?id=2839

f[k]        :1
f[k+1]    :-C(k+1,k)
f[k+2]    :+C(k+2,k)

+C(k+1,k)*C(k+2,k+1)

f[k]        :1
f[k+1]    :-C(k+1,k)
f[k+2]    :-C(k+2,k)+C(k+1,k)*C(k+2,k+1) = +C(k+2,k)
f[k+3]    :-C(k+3,k)+C(k+1,k)*C(k+3,k+1)-C(k+2,k)*C(k+3,k+2) = -C(k+3,k)
f[k+4]    :-C(k+4,k)+C(k+1,k)*C(k+4,k+1)-C(k+2,k)*C(k+4,k+2)+C(k+3,k)*C(k+3,k+4) = +C(k+4,k)
......

∑ (-1)^(i-k)*C(i,k)*f[i]
i=k

#include<cstdio>
#include<cstring>
#include<iostream>
#define _ %mod
#define MAXN 1005000
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
const int mod=1000000007;
int w[MAXN],f[MAXN],fac[MAXN],inv[MAXN];
int N,K,ANS;
int C(int n,int m){//n中选 m个
return ((1ll*fac[n]*inv[m])_*inv[n-m])_;
}
int pow(int a,int b){
int now=1;
while(b){
if(b&1) now=(1ll*now*a)_;
a=(1ll*a*a)_;
b>>=1;
}
return now;
}
void pre(int n){
w[0]=2;	fac[0]=1;
for(int i=1;i<=n;i++)
fac[i]=(1ll*fac[i-1]*i)_;
inv[n]=pow(fac[n],mod-2);
for(int i=n-1;i>=0;i--)
inv[i]=(1ll*inv[i+1]*(i+1))_;
for(int i=1;i<=n;i++)
w[i]=(1ll*w[i-1]*w[i-1])_;
for(int i=0;i<=n;i++)
f[i]=(1ll*(w[n-i]-1)*C(n,i))_;
}
int main()
{
scanf("%d%d",&N,&K);
pre(N);
for(int i=K;i<=N;i++)
ANS=(1ll*C(i,K)*f[i]*((i-K)&1?-1:1)+ANS)_;
ANS=(ANS+mod)_;
printf("%d",ANS);
return 0;
}


Do not go gentle into that good night.
Rage, rage against the dying of the light.
————Dylan Thomas
posted @ 2017-12-12 19:21  *ZJ  阅读(152)  评论(0编辑  收藏  举报