题目传送门
分析:
良心CF不卡(O(3^n))(错乱
(s_a)(s_b)组合我们看做两个不相交集合合并成一个集合作贡献
(s_d)(s_e)就是裸的异或卷积
中间三个就是与卷积了
第一个目前我们只会(O(3^n)),于是引入子集卷积
最初的式子为:
(F[i]=sum_{j|k=i}~[j&k=0]F[j]F[k])
设(sz[i])表示(i)在二进制状态下(1)的个数
我们在每一个&F[i]&前加一位变成(F[sz[i]][i])
(F[sz[i]][i]=sum_{j|k=i,sz[j]+sz[k]=sz[i]}~~~F[sz[j]][j]F[sz[k]][k])
这样做或卷积就没有问题了
复杂度是(O(2^nn^2)),可以做(n geq 18)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#define maxn 1000005
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define inv2 500000004
using namespace std;
inline int getint()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
int n,len=1<<17,ans;
int a[maxn],b[maxn],c[maxn],d[18][maxn],e[18][maxn],f[maxn],cnt[maxn],s[maxn];
inline int upd(int x){return x<MOD?x:x-MOD;}
inline void FWT_and(int *a,int len,int op)
{
for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=(i<<1))for(int k=0;k<i;k++)
if(~op)a[j+k]=upd(a[j+k]+a[i+j+k]);
else a[j+k]=upd(a[j+k]+MOD-a[i+j+k]);
}
inline void FWT_or(int *a,int len,int op)
{
for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=(i<<1))for(int k=0;k<i;k++)
if(~op)a[i+j+k]=upd(a[j+k]+a[i+j+k]);
else a[i+j+k]=upd(a[i+j+k]+MOD-a[j+k]);
}
inline void FWT_xor(int *a,int len,int op)
{
for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=(i<<1))for(int k=0;k<i;k++)
{
int x=a[j+k],y=a[i+j+k];
a[j+k]=upd(x+y),a[i+j+k]=upd(x+MOD-y);
if(!~op)a[j+k]=1ll*a[j+k]*inv2%MOD,a[i+j+k]=1ll*a[i+j+k]*inv2%MOD;
}
}
int main()
{
n=getint();
for(int i=1;i<=n;i++)s[getint()]++;
for(int i=1;i<len;i++)cnt[i]=cnt[i>>1]+(i&1);
f[1]=1;
for(int i=2;i<len;i++)f[i]=upd(f[i-1]+f[i-2]);
for(int i=0;i<len;i++)d[cnt[i]][i]=s[i];
for(int i=0;i<=17;i++)FWT_or(d[i],len,1);
for(int i=0;i<=17;i++)for(int j=0;j<=i;j++)for(int k=0;k<len;k++)
e[i][k]=upd(e[i][k]+1ll*d[j][k]*d[i-j][k]%MOD);
for(int i=0;i<=17;i++)FWT_or(e[i],len,-1);
for(int i=0;i<len;i++)a[i]=1ll*f[i]*e[cnt[i]][i]%MOD;
for(int i=0;i<len;i++)b[i]=1ll*s[i]*f[i]%MOD;
FWT_xor(s,len,1);
for(int i=0;i<len;i++)c[i]=1ll*s[i]*s[i]%MOD;
FWT_xor(c,len,-1);
for(int i=0;i<len;i++)c[i]=1ll*c[i]*f[i]%MOD;
FWT_and(a,len,1),FWT_and(b,len,1),FWT_and(c,len,1);
for(int i=0;i<len;i++)a[i]=1ll*a[i]*b[i]%MOD*c[i]%MOD;
FWT_and(a,len,-1);
for(int i=0;i<17;i++)ans=upd(ans+a[1<<i]);
printf("%d
",ans);
}