Loading

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;
}
posted @ 2021-03-30 23:07  Gemini7X  阅读(48)  评论(0编辑  收藏  举报
Title