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

 

posted @ 2017-07-28 17:05  _yxg123  阅读(205)  评论(0编辑  收藏  举报