题意:
有
n个整数,问从他们中取出若干个数字相与之后结果是
0的有多少组。
思路:
这道题需要51nod1406作为基础,链接:
http://blog.csdn.net/bahuia/article/details/55653495
因为从正面考虑直接求解相与和为0不好做,所以可以利用容斥来解决,因为数的总量就这么大,所以我们在总数中减掉相与和为1的方案数,相与和为2的方案数等等,就可以得到最后的答案,可以用dp求出来对于每一个x都有a[i] & x == x的个数(也就是1406的结果)。设这个数是f(x),则从这f(x)中任意选择了2^f(x)-1种方案得到的相与和其中的二进制位上的1的个数都不会比x的1的个数小,这样就枚举x,看x二进制中1的个数,若是奇数就减,偶数就加,最后得到结果。
稳妥起见加个输入挂。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 10;
const ll MOD = 1e9 + 7;
int a[MAXN], dp[MAXN];
ll two[MAXN];
void read(int &res) {
res = 0;
char ch;
if (ch >= '0' && ch <= '9') {
res = ch - '0';
}
while ((ch = getchar()) >= '0' && ch <= '9') {
res = res * 10 + (ch - '0');
}
}
void init() {
two[0] = 1;
for (int i = 1; i <= 1000000; i++) {
two[i] = two[i - 1] * 2 % MOD;
}
}
int main() {
init();
int n, Max = 0;
read(n);
for (int i = 1; i <= n; i++) {
read(a[i]);
dp[a[i]]++;
Max = max(Max, a[i]);
}
if (n == 1) {
if (a[1] == 0) puts("1");
else puts("0");
return 0;
}
int maxbit = 0, tmp = Max;
while (tmp) {
tmp >>= 1;
++maxbit;
}
for (int i = 0; i < maxbit; i++) {
for (int j = 1; j <= Max; j++) {
if (j & (1 << i)) {
dp[j - (1 << i)] += dp[j];
}
}
}
dp[0] = n;
ll ans = 0;
for (int i = 0; i <= Max; i++) {
int cnt = 0;
for (int j = 0; j < maxbit; j++) {
if (i & (1 << j)) ++cnt;
}
if (cnt & 1) ans = ((ans - (two[dp[i]] - 1)) % MOD + MOD) % MOD;
else ans = (ans + (two[dp[i]] - 1)) % MOD;
}
printf("%lld\n", ans);
return 0;
}