title
题目
solution
(sa∣sb)&sc&(sd⊕se)=2i,i∈Z;sa&sb=0(s_a|s_b)\&s_c\&(s_d⊕s_e)=2^i,i∈Z;s_a\&s_b=0(sa∣sb)&sc&(sd⊕se)=2i,i∈Z;sa&sb=0
令i=sa∣sb,j=sc,d=sd⊕sei=s_a|s_b,j=s_c,d=s_d⊕s_ei=sa∣sb,j=sc,d=sd⊕se
∑x∑i&j&k=xfibi∗fibj∗fibk∗(∑sa∣sb=i,sa&sb=01)∗(∑sc=j1)∗(∑sd⊕se=k1)\sum_{x}\sum_{i\&j\&k=x}fib_i*fib_j*fib_k*(\sum_{s_a|s_b=i,s_a\&s_b=0}1)*(\sum_{s_c=j}1)*(\sum_{s_d⊕s_e=k}1)x∑i&j&k=x∑fibi∗fibj∗fibk∗(sa∣sb=i,sa&sb=0∑1)∗(sc=j∑1)∗(sd⊕se=k∑1)
令fi=(∑sa∣sb=i,sa&sb=01),gj=(∑sc=j1),hk=(∑sd⊕se=k1)f_i=(\sum_{s_a|s_b=i,s_a\&s_b=0}1),g_j=(\sum_{s_c=j}1),h_k=(\sum_{s_d⊕s_e=k}1)fi=(∑sa∣sb=i,sa&sb=01),gj=(∑sc=j1),hk=(∑sd⊕se=k1)
fff就是子集卷积直接做;ggg不做操作;hhh就是常规的FWT_xorFWT\_xorFWT_xor卷积
最后三个一起带着各自的斐波拉契权值,做个FWT_andFWT\_andFWT_and卷积即可
code
#include <cstdio>
#include <cstring>
#define mod 1000000007
#define int long long
#define maxn 1 << 18
int n, ret, inv = ( mod + 1 ) >> 1;
int f[maxn], g[maxn], h[maxn], tmp[maxn], ans[maxn], fib[maxn];
int dp[20][maxn];void FWT_or( int *v, int opt ) {for( int i = 1;i < maxn;i <<= 1 )for( int j = 0;j < maxn;j += ( i << 1 ) )for( int k = 0;k < i;k ++ )v[j + k + i] = ( v[j + k + i] + v[j + k] * opt + mod ) % mod;
}void FWT_and( int *v, int opt ) {for( int i = 1;i < maxn;i <<= 1 ) for( int j = 0;j < maxn;j += ( i << 1 ) )for( int k = 0;k < i;k ++ )v[j + k] = ( v[j + k] + v[j + k + i] * opt + mod ) % mod;;
}void FWT_xor( int *v, int opt ) {for( int i = 1;i < maxn;i <<= 1 )for( int j = 0;j < maxn;j += ( i << 1 ) )for( int k = 0;k < i;k ++ ) {int x = v[j + k], y = v[j + k + i];v[j + k] = ( x + y ) % mod;v[j + k + i] = ( x - y + mod ) % mod;if( opt == -1 ) {v[j + k] = v[j + k] * inv % mod;v[j + k + i] = v[j + k + i] * inv % mod;}}
}signed main() {scanf( "%lld", &n );for( int i = 1, x;i <= n;i ++ ) {scanf( "%lld", &x );f[x] ++, g[x] ++, h[x] ++;}fib[1] = 1;for( int i = 2;i < maxn;i ++ )fib[i] = ( fib[i - 1] + fib[i - 2] ) % mod;for( int i = 0;i < maxn;i ++ )dp[__builtin_popcount( i )][i] = f[i], f[i] = 0;n = 18;for( int i = 0;i < n;i ++ )FWT_or( dp[i], 1 );for( int i = 0;i < n;i ++ ) {memset( tmp, 0, sizeof( tmp ) );for( int j = 0;j <= i;j ++ )for( int k = 0;k < maxn;k ++ )tmp[k] = ( tmp[k] + dp[j][k] * dp[i - j][k] % mod ) % mod;FWT_or( tmp, -1 );for( int j = 0;j < maxn;j ++ )if( __builtin_popcount( j ) == i )f[j] = ( f[j] + tmp[j] ) % mod;}FWT_xor( h, 1 );for( int i = 0;i < maxn;i ++ )h[i] = h[i] * h[i] % mod;FWT_xor( h, -1 ); for( int i = 0;i < maxn;i ++ )f[i] = f[i] * fib[i] % mod, g[i] = g[i] * fib[i] % mod, h[i] = h[i] * fib[i] % mod;FWT_and( f, 1 ), FWT_and( g, 1 ), FWT_and( h, 1 );for( int i = 0;i < maxn;i ++ )ans[i] = f[i] * g[i] % mod * h[i] % mod;FWT_and( ans, -1 );for( int i = 1;i < maxn;i <<= 1 )ret = ( ret + ans[i] ) % mod;printf( "%lld\n", ret );return 0;
}