「BZOJ2839」収集回数
効果の件名:
含ま\(N- \)セットの数である\(2 ^ N \)サブセットを、それらの交差点が正確になるように、フォーカスのセットは、サブから(少なくとも一つの)要素の数を一部をとる(K \)\、プログラム番号、答を見つける(1E9 + 7 \)\剰余を。
最初の非常に直感的なアイデアを考える:我々インペリアル\(k個の\) 、それらの交差点の数、などのようなプログラムの数(\ \ Binom {N-} {K} \) 、これを含有しながら\(k個の\)を数値の組の数\(NK 2 ^ {} \) 、各セットが選択されていない選択されたが、問題の意味に応じて、必ずしもすべてが選択することができない2つの状態を有するので、解の総数が得られた\(b_k \)する
\ [b_k = \ binom {N
} {K}(2 ^ {2 ^ {NK} - 1)\] 、これは我々が望む結果は、セットの交差点を設定し、これらのトランザクションを提供することを要求されません\(J \)からなるセットの数\(\) 、厳選\(K \)からなるセットの数\(B \) 、次いで(B \が\をsubseteq)\、時間、プログラムは、一度カウントされます合計にカウントされます\(\ binom JK \)回。
交差点を正確に提供\(K \)プログラム要素の数\(a_k \)がある
\ [b_k = \ sum_ {I
= K} ^ N \ binom IK a_iを\] そしてここでは、コンテンツを使用することができ放出撥原理が、すなわち、二項反転を使用することがより便利である
\ [F(K)= \ sum_ {i = K} ^ N \ binom IKG(I)\ IFF G(K)= \ sum_ { I = K} ^ N(-1
)^ {IK} \ binom IKF(I)\] この式は、元の式を代入することにより直接得ることができます。
同様に、別の反転二項形式もある
\ [F(N)= \ sum_ {i = K} ^ N \ binom NIG(I)\ IFF G(N)= \ sum_ {i = kは} ^ N(-1)^ {NI
} \ binom NIF(I)\] 証明方法は、本明細書に記載されていません。
この質問について、すなわち、どのような答えを得るために、私たちの直接反転、
\ [a_k = \ sum_ {I = K} ^ n個(-1)^ {IK} \ binom IK \ binom NK(2 ^ {2 ^ { NK} - 1)\]
の時間複雑度\(O(N)\) 。
\(\ texttt {コード:} \)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll p=1e9+7;
const ll maxn=1e6+5;
ll ksm(ll a,ll b,ll p){
ll ans=1;
for(;b;b>>=1,a=1ll*a*a%p)
if(b&1) ans=1ll*ans*a%p;
return ans;
}
ll fac[maxn],inv[maxn];
ll C(ll n,ll m){
if(n<m) return 0;
return 1ll*fac[n]*inv[m]%p*inv[n-m]%p;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
ll n,k;
cin>>n>>k;
fac[0]=1;
for(ll i=1;i<=n;++i) fac[i]=1ll*fac[i-1]*i%p;
inv[n]=ksm(fac[n],p-2,p);
for(ll i=n-1;i>=0;--i) inv[i]=1ll*inv[i+1]*(i+1)%p;
ll ans=0;
for(ll i=k;i<=n;++i){
ans=(ans+1ll*((i-k)&1?(-1):(1))*(C(i,k)*C(n,i)%p*(ksm(2,ksm(2,n-i,p-1),p)%p-1+p))%p+p)%p;
}
cout<<ans<<'\n';
return 0;
}