CodeForces 449D Jzzhu and Numbers 【DP+容斥】
题目链接:
http://codeforces.com/contest/449/problem/D
题意:
给n个数,求and起来最后为0的集合方案数有多少
思路:
http://blog.csdn.net/drcarl/article/details/54616345
http://www.cnblogs.com/barrier/p/6670514.html?utm_source=itdadao&utm_medium=referral
先求有多少种情况使得与出来的结果不为0,考察有多少元素在某些二进制位上为1,则它们与出来在这些位上也必然为1。 令函数f(x)为满足ai&x=x的a的个数。 这里的x就是一个bitmask,满足ai&x=x的a,也就意味着这些a在x为1的那些二进制位上为1。
那么有了f(x)以后,就可以用容斥原理求出有多少种使得结果不为1的情况。再令g(x)为x的二进制位中1的个数,那么所有结果不为1的情况:
上篇博客 是求f(x)的。http://www.cnblogs.com/yxg123123/p/7251206.html
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 1e6+10; const int mod = 1e9+7; int n,dp[maxn]; ll qpow(ll a,ll b){ ll res = 1; while(b){ if(b&1) res = (res*a)%mod; a = (a*a)%mod; b >>= 1; } return res; } int main(){ cin >> n; int mx = 0; for(int i=1; i<=n; i++){ int x = read(); dp[x] ++; mx = max(mx,x); } int bit = 0; while(mx){ mx >>= 1; bit++; } for(int j=0; j<bit; j++){ for(int i=1; i<maxn; i++) if(i & (1<<j)) dp[i-(1<<j)] += dp[i]; } dp[0] = n; ll ans = qpow(2,n)-1; for(int i=1; i<maxn; i++){ int cnt = 0, t = i; while(t) { if(t&1) cnt++; t>>=1;} if(cnt&1) ans = (ans-(qpow(2,dp[i])-1)+mod)%mod; else ans = (ans+qpow(2,dp[i])-1)%mod; } cout << ans << endl; return 0; }