#容斥#51nod 1407 与与与与

题目

给出 (n) 个数,问有多少个子集的按位与为0


分析

考虑容斥,设 (f[i]) 表示有多少个数按位与为 (x),满足 (x&i=i)

那么答案就是 (sum_{i=0}^{mx}(2^{f[i]}-1)(-1)^{cnt_i}),这个 (f) 直接子集卷起来就可以了


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=1000011,mod=1000000007;
int n,two[N],xo[N],c[N],ans,mx;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
int mo(int x,int y){return x+y>=mod?x+y-mod:x+y;} 
int main(){
	n=iut(),two[0]=1;
	for (int i=1;i<=n;++i) two[i]=mo(two[i-1],two[i-1]);
	for (int i=1,x;i<=n;++i) x=iut(),++c[x],mx=mx>x?mx:x;
	for (int i=1;i<=mx;++i) xo[i]=xo[i&(i-1)]+1;
	for (int j=0;j<20;++j)
	for (int i=1;i<=mx;++i)
	    if ((i>>j)&1) c[i^(1<<j)]+=c[i];
    for (int i=0;i<=mx;++i)
    if (xo[i]&1) ans=mo(ans,mod-two[c[i]]+1);
        else ans=mo(ans,two[c[i]]-1);
    return !printf("%d",ans);
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15512024.html