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

  

posted @ 2018-05-26 12:34  longint  阅读(138)  评论(0编辑  收藏  举报