比较简单的DP吧,我的做法是正反计算一次,其中另外用dps记录当前选第i个数异或的结果的方法数
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=1e3+10;
const int maxm=1024*2;
const int mod=1e9+7;
int n,a[maxn];
int dp[maxn][maxm][2],dps[maxn][maxm][2];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int maxi=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
memset(dps,0,sizeof(dps));
for(int i=1;i<=n;i++)
{
dp[i][a[i]][0]=1;
dps[i][a[i]][0]=1;
for(int j=0;j<maxm;j++)
if(dp[i-1][j][0])
{
dp[i][j][0]=(dp[i][j][0]+dp[i-1][j][0])%mod;
dp[i][j^a[i]][0]=(dp[i][j^a[i]][0]+dp[i-1][j][0])%mod;
dps[i][j^a[i]][0]=(dps[i][j^a[i]][0]+dp[i-1][j][0])%mod;
}
}
for(int i=n;i>=1;i--)
{
dp[i][a[i]][1]=1;
for(int j=0;j<maxm;j++)
if(dp[i+1][j][1])
{
dp[i][j][1]=(dp[i][j][1]+dp[i+1][j][1])%mod;
dp[i][j&a[i]][1]=(dp[i][j&a[i]][1]+dp[i+1][j][1])%mod;
}
}
long long ans=0;
for(int i=1;i<n;i++)
for(int j=0;j<maxm;j++)
if(dps[i][j][0])
ans=(ans+(long long)dps[i][j][0]*(long long)dp[i+1][j][1])%mod;
printf("%I64d\n",ans);
}
return 0;
}