CTSC2017 吉夫特
考虑 \(n\choose m\) 什么时候是奇数。
拆开得 \({n\choose m}=\frac{n!}{m!(n-m)!}\),设 \(f(x)=\sum\limits_{i\ge 1}\frac{n!}{2^i}\)。那么显然仅有 \(f(n)=f(m)+f(n-m)\) 时 \({n\choose m}\equiv 1\pmod 2\)。设 \(g(n)=n=g(n/2)+n/2+n\bmod 2=f(n)+popcount(n)\)。于是有 \(f(n)=popcount(n)-n\)。也就是说要满足 \(popcount(n)=popcount(m)+popcount(n-m)\)。其中 \(popcount\) 代表二进制下有多少个 \(1\)。
而 \(popcount(m)+popcount(n-m)\ge popcount(n)\) 当且仅当在 \(m\& n=m\) 时才取等。
那么直接dp,然后子集枚举即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000000;
const int mod = 1000000007;
int n, a[MAXN], pos[MAXN], f[MAXN];
int ans;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", a + i), pos[a[i]] = i;
for (int i = n; i >= 1; i--) {
f[i] = 1;
for (int j = a[i] & (a[i] - 1); j; j = (j - 1) & a[i]) {
f[i] = (f[i] + f[pos[j]]) % mod;
}
ans = (ans + f[i] - 1) % mod;
}
printf("%d\n", ans);
return 0;
}