「BZOJ2839」収集回数

「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;
}

おすすめ

転載: www.cnblogs.com/HenryHuang-Never-Settle/p/11707108.html