[CTSC2017]吉夫特

题解

考虑 (nchoose m) 什么时候是奇数。

拆开得 ({nchoose m}=frac{n!}{m!(n-m)!}),设 (f(x)=sumlimits_{ige 1}frac{n!}{2^i})。那么显然仅有 (f(n)=f(m)+f(n-m))({nchoose m}equiv 1pmod 2)。设 (g(n)=n=g(n/2)+n/2+nmod 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
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/zcr-blog/p/14599404.html