思路:各种状态转移统计一下,然后乘啊乘。G++T了,C++过了。
这里解释下吧:
a[i][j]代表前i个中包含第i个且异或值为j的集合的个数
b[i][j]代表前i个全部的异或值为j的集合的个数(与a不同,这里包含了包含第i个和不包含第i的情况)
c[i][j]代表第i个到最后一个中,包含第i个且 与运算的值为j的集合个数(这里的确用不着)
d[i][j]代表第i个到最后一个中,全部与运算为j的集合个数(可包含i,也可不包含i)
我这里用的是a与d运算求结果,事实上也可用b与c来算。至于为什么乘啊乘应该不难理解吧,不理解自己想吧。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const long long M=1e9+7;
long long a[1111][1111],b[1111][1111],c[1111][1111],d[1111][1111];
int n,aa[1111];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&aa[i]);
if(n==1||n==0)
{
printf("0\n");
continue;
}
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
a[1][aa[1]]=1;
b[1][aa[1]]=1;
for(int i=2;i<=n;i++)
{
a[i][aa[i]]+=1;
b[i][aa[i]]+=1;
for(int j=0;j<1024;j++)
{
if(b[i-1][j])
{
a[i][j^aa[i]]+=b[i-1][j];
b[i][j^aa[i]]+=b[i-1][j];
b[i][j]+=b[i-1][j];
a[i][j^aa[i]]%=M;
b[i][j^aa[i]]%=M;
b[i][j]%=M;
}
}
}
c[n][aa[n]]=1;
d[n][aa[n]]=1;
for(int i=n-1;i>=1;i--)
{
c[i][aa[i]]+=1;
d[i][aa[i]]+=1;
for(int j=0;j<1024;j++)
{
if(d[i+1][j])
{
c[i][j&aa[i]]+=d[i+1][j];
d[i][j&aa[i]]+=d[i+1][j];
d[i][j]+=d[i+1][j];
c[i][j&aa[i]]%=M;
d[i][j&aa[i]]%=M;
d[i][j]%=M;
}
}
}
long long ans=0;
for(int i=1;i<n;i++)
{
for(int j=0;j<1024;j++)
{
if(a[i][j]&&d[i+1][j])
{
ans+=a[i][j]*d[i+1][j];
ans%=M;
}
}
}
printf("%I64d\n",ans);
}
return 0;
}