CF914G Sum the Fibonacci

https://www.luogu.com.cn/problem/CF914G

首先按照套路肯定是先记下每个数出现的次数
然后大力FWT+FST即可
code:

#include<bits/stdc++.h>
#define mod 1000000007
#define ll long long
using namespace std;
const int N = (1 << 17) + 5;
const ll inv2 = (1 + mod) / 2;
void fwtor(ll *a, int n, int o) {
    for(int len = 2; len <= n; len <<= 1)
        for(int j = 0; j < n; j += len)
            for(int k = j; k < j + (len >> 1); k ++)
                a[k + (len >> 1)] = (a[k + (len >> 1)] + o * a[k] + mod) % mod;
}
void fwtand(ll *a, int n, int o) {
    for(int len = 2; len <= n; len <<= 1)
        for(int j = 0; j < n; j += len)
            for(int k = j; k < j + (len >> 1); k ++)
                a[k] = (a[k] + o * a[k + (len >> 1)] + mod) % mod;
}

void fwtxor(ll *a, int n, int o) {
    for(int len = 2; len <= n; len <<= 1)
        for(int j = 0; j < n; j += len)
            for(int k = j; k < j + (len >> 1); k ++) {
                ll X = a[k], Y = a[k + (len >> 1)];
                a[k] = (X + Y) % mod, a[k + (len >> 1)] = (X - Y + mod) % mod;
                if(o == -1) a[k] = a[k] * inv2 % mod, a[k + (len >> 1)] = a[k + (len >> 1)] * inv2 % mod;
            }
}
int n, fib[N], cnt[N];
ll f[19][N], a[N], b[N], c[N], ls[N];
void init() {
    fib[1] = 1;
    for(int i = 2; i < N; i ++) fib[i] = (fib[i - 1] + fib[i - 2]) % mod;
    for(int i = 1; i < N; i ++) cnt[i] = cnt[i >> 1] + (i & 1);
}
void FST(int n) {
    for(int i = 0; i <= 17; i ++) fwtor(f[i], n, 1);
    for(int i = 0; i <= 17; i ++) {
        for(int S = 0; S < n; S ++) ls[S] = 0;
        for(int j = 0; j <= i; j ++)
            for(int S = 0; S < n; S ++)
                ls[S] = (ls[S] + f[j][S] * f[i - j][S] % mod) % mod;
        fwtor(ls, n, -1);
        for(int S = 0; S < n; S ++)
            if(cnt[S] == i) a[S] = (a[S] + ls[S]) % mod;
    }
}
int main() {
    init();
    scanf("%d", &n);
    for(int i = 1, x; i <= n; i ++) {
        scanf("%d", &x);
        f[cnt[x]][x] ++, b[x] = (b[x] + fib[x]) % mod, c[x] ++;
    }
    int len = (1 << 17);
    FST(len);
    fwtxor(c, len, 1);
    for(int i = 0; i < len; i ++) c[i] = c[i] * c[i] % mod;
    fwtxor(c, len, -1);
    for(int i = 0; i < len; i ++) a[i] = a[i] * fib[i] % mod, c[i] = c[i] * fib[i] % mod;
    fwtand(a, len, 1), fwtand(b, len, 1), fwtand(c, len, 1);
    for(int i = 0; i < len; i ++) a[i] = a[i] * b[i] % mod * c[i] % mod;
    fwtand(a, len, -1);
    ll ans = 0;
    for(int i = 1; i < len; i <<= 1) ans = (ans + a[i]) % mod;
    printf("%lld", ans);
    return 0;
}
posted @ 2021-07-22 14:34  lahlah  阅读(32)  评论(0编辑  收藏  举报