码迷,mamicode.com
首页 > 其他好文 > 详细

【bzoj 2839】集合计数

时间:2019-03-31 13:49:14      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:www   mod   .com   har   else   bzoj   tps   http   getchar   

权限题

根据广义容斥的套路就很好做了

\(g_i\)表示交集至少有\(i\)个元素,\(f_i\)表示交集恰好有\(i\)个元素

显然有

\[g_i=\sum_{j=i}^n\binom{j}{i}f_j\]

二项式反演可得

\[f_i=\sum_{j=i}^n(-1)^{j-i}\binom{j}{i}g_j\]

我们求得就是\(f_k\)

我们考虑\(g\)如何求

我们先从\(n\)个元素里选择\(j\)个元素作为我们的交集,这里是\(\binom{n}{j}\),之后对于剩下的\(n-j\)个元素构成的\(2^{n-j}\)个子集我们从里面任意选择一些,之后并上这\(j\)个元素就可以了

于是\(g_j=2^{2^{n-j}}\),就是\(2^{n-j}\)个子集都可以选或者不选

记得指数上对\(mod-1\)取模

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=1000005;
const LL mod=1000000007;
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
LL fac[maxn],inv[maxn],pw[maxn];
int n,k;
inline LL ksm(LL a,int b) {
    LL S=1;
    while(b) {if(b&1) S=S*a%mod;b>>=1;a=a*a%mod;}
    return S;
}
inline LL C(int n,int m) {
    if(m>n) return 0;
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main() {
    n=read(),k=read();
    fac[0]=1;
    for(re int i=1;i<=n;i++) fac[i]=(1ll*i*fac[i-1])%mod;
    inv[n]=ksm(fac[n],mod-2);
    for(re int i=n-1;i>=0;--i) inv[i]=(1ll*(i+1)*inv[i+1])%mod;
    pw[0]=1;
    for(re int i=1;i<=n;i++) pw[i]=(2ll*pw[i-1])%(mod-1);
    LL ans=0;
    for(re int i=k;i<=n;i++) {
        LL g=C(n,i)*ksm(2,pw[n-i])%mod;
        if((i-k)&1) ans=(ans-C(i,k)*g%mod+mod)%mod;
            else ans=(ans+C(i,k)*g%mod)%mod;
    }
    printf("%d\n",(int)ans);
    return 0;
}

【bzoj 2839】集合计数

标签:www   mod   .com   har   else   bzoj   tps   http   getchar   

原文地址:https://www.cnblogs.com/asuldb/p/10630880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!