CF449D
题目大意:给定n个数,问有多少子序列使得子序列中的数&起来=0
做法:显然的容斥题目
ans=2^n-1-(至少1位为1-至少两位为1+至少3位为1......)
我们考虑用dp[i]表示包含i这个状态的数有多少个
显然我们可以枚举所有可能的有1的状态
for i=1 to 1e6 do begin
ans=2^n-1-sigma((-1)^g[i]*(2^dp[i]-1))
其中g[i]表示i这个状态下有几个1
显然包含i这个状态的数都可以选择,只要选的是这dp[i]个数
那么至少i状态这几位都是1
代码:
#include<bits/stdc++.h> #define Mod 1000000007 #define N 1000005 using namespace std; int n,bin[2*N],dp[2*N],x; int main(){ scanf("%d",&n); bin[0]=1; for (int i=1;i<=1000000;i++) bin[i]=1ll*bin[i-1]*2%Mod; for (int i=1;i<=n;i++) scanf("%d",&x),dp[x]++; for (int j=0;j<=20;j++) for (int i=1;i<=1000000;i++)//dp[i]表示包含i的数有多少 if ((1<<j)&i) (dp[i^(1<<j)]+=dp[i])%=Mod; int ans=0; for (int i=0;i<=1000000;i++){ int opt=1; for (int j=0;j<=20;j++) if ((1<<j)&i) opt=-opt; ans=1ll*(ans+(1ll*opt*(bin[dp[i]]-1)%Mod))%Mod; ans=(ans+Mod)%Mod; } printf("%d\n",ans%Mod); return 0; }