[高维前缀和] Codeforces 449D

来源:互联网 发布:mac os最新版本是多少 编辑:程序博客网 时间:2024/05/17 03:10

题意即选一些集合,并为空集的方案数。容易想到容斥

ans=i=0220(1)cnt(i)(2f(i)1)

其中f(i) 表示包含 i 的集合的个数, cnt(i) 表示 i1 的个数。

现在只需求 f(i)f(i)=[x & i=i]是个典型的高维前缀和问题。也可以理解成一个简单的 DP 。具体见代码吧。

#include<cstdio>#include<algorithm>using namespace std;typedef long long LL;const int maxn=1048576+10,M=19,MOD=1000000007;int n,ans,f[maxn];int Pow(LL a,int b){    LL res=1;    for(;b;b>>=1,a=a*a%MOD) if(b&1) res=(res*a)%MOD;    return res;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++){        int x; scanf("%d",&x);        f[x]++;    }    for(int i=0;i<=M;i++)     for(int j=0;j<=(1<<M+1)-1;j++)      if(!((j>>i)&1)) (f[j]+=f[j|(1<<i)])%=MOD;    for(int i=0;i<=(1<<M+1)-1;i++){        int cnt=0; for(int j=0;j<=M;j++) if((i>>j)&1) cnt++;        (ans+=((cnt&1)?-1:1)*(Pow(2,f[i])-1))%=MOD;     }    printf("%d\n",(ans+MOD)%MOD);    return 0;}
原创粉丝点击