解:发现我们对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 ", ans); 109 return 0; 110 }