CF914G Sum the Fibonacci

解:发现我们对a和b做一个集合卷积,对d和e做一个^FWT,然后把这三个全部对位乘上斐波那契数,然后做&FWT就行了。

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 150010, MO = 1e9 + 7, inv2 = (MO + 1) / 2;
  4 
  5 int n, lm, f[N], a[N], b[N], c[N], cnt[N], d[20][N], e[20][N];
  6 
  7 inline void FWT_or(int *a, int n, int f) {
  8     for(int len = 1; len < n; len <<= 1) {
  9         for(int i = 0; i < n; i += (len << 1)) {
 10             for(int j = 0; j < len; j++) {
 11                 a[i + len + j] = ((a[i + len + j] + f * a[i + j]) % MO + MO) % MO;
 12             }
 13         }
 14     }
 15     return;
 16 }
 17 
 18 inline void FWT_and(int *a, int n, int f) {
 19     for(int len = 1; len < n; len <<= 1) {
 20         for(int i = 0; i < n; i += (len << 1)) {
 21             for(int j = 0; j < len; j++) {
 22                 a[i + j] = ((a[i + j] + f * a[i + len + j]) % MO + MO) % MO;
 23             }
 24         }
 25     }
 26     return;
 27 }
 28 
 29 inline void FWT_xor(int *a, int n, int f) {
 30     for(int len = 1; len < n; len <<= 1) {
 31         for(int i = 0; i < n; i += (len << 1)) {
 32             for(int j = 0; j < len; j++) {
 33                 int t = a[i + len + j];
 34                 a[i + len + j] = (a[i + j] - t + MO) % MO;
 35                 a[i + j] = (a[i + j] + t) % MO;
 36                 if(f == -1) {
 37                     a[i + len + j] = 1ll * a[i + len + j] * inv2 % MO;
 38                     a[i + j] = 1ll * a[i + j] * inv2 % MO;
 39                 }
 40             }
 41         }
 42     }
 43     return;
 44 }
 45 
 46 int main() {
 47     int n;
 48     scanf("%d", &n);
 49     for(int i = 1, x; i <= n; i++) {
 50         scanf("%d", &x);
 51         a[x]++;
 52     }
 53     n = 17;
 54     lm = 1 << 17;
 55     cnt[1] = f[1] = 1;
 56     for(int i = 2; i < lm; i++) {
 57         f[i] = (f[i - 1] + f[i - 2]) % MO;
 58         cnt[i] = cnt[i - (i & (-i))] + 1;
 59     }
 60     memcpy(c, a, lm * sizeof(int));
 61 
 62     for(int i = 0; i < lm; i++) {
 63         d[cnt[i]][i] = a[i];
 64     }
 65     for(int i = 0; i <= n; i++) {
 66         FWT_or(d[i], lm, 1);
 67     }
 68     for(int i = 1; i <= n; i++) {
 69         for(int j = 0; j <= i; j++) {
 70             for(int s = 0; s < lm; s++) {
 71                 e[i][s] = (e[i][s] + 1ll * d[j][s] * d[i - j][s] % MO) % MO;
 72             }
 73         }
 74     }
 75     for(int i = 0; i <= n; i++) {
 76         FWT_or(e[i], lm, -1);
 77     }
 78     for(int i = 0; i < lm; i++) {
 79         b[i] = 1ll * e[cnt[i]][i] * f[i] % MO;
 80     }
 81 
 82     FWT_xor(c, lm, 1);
 83     for(int i = 0; i < lm; i++) {
 84         c[i] = 1ll * c[i] * c[i] % MO;
 85     }
 86     FWT_xor(c, lm, -1);
 87     for(int i = 0; i < lm; i++) {
 88         c[i] = 1ll * c[i] * f[i] % MO;
 89     }
 90 
 91     for(int i = 0; i < lm; i++) {
 92         a[i] = 1ll * a[i] * f[i] % MO;
 93     }
 94 
 95     FWT_and(a, lm, 1);
 96     FWT_and(b, lm, 1);
 97     FWT_and(c, lm, 1);
 98     for(int i = 0; i < lm; i++) {
 99         a[i] = 1ll * a[i] * b[i] % MO * c[i] % MO;
100     }
101     FWT_and(a, lm, -1);
102 
103     int ans = 0;
104     for(int i = 1; i < lm; i <<= 1) {
105         ans = (ans + a[i]) % MO;
106     }
107 
108     printf("%d\n", ans);
109     return 0;
110 }
AC代码

猜你喜欢

转载自www.cnblogs.com/huyufeifei/p/10723839.html