枚举分界线,将分界线上的元素强行划分给一边,另一边随意,然后求组合数即可。
附代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
long long int dp[1005][1025]; //记录前i项异或结果为t的组合数
long long int ddp[1005][1025]; //记录后i项与的结果为t的包含第i项的组合数
long long int dpp[1005][1025]; //记录后i项与的结果为t的可包含可不包含第i项的组合数
int a[1001];
int n;
const int mod=1000000000+7;
int main()
{
int T;
cin>>T;
while (T--)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
memset(ddp,0,sizeof(ddp));
memset(dpp,0,sizeof(dpp));
dpp[n][a[n]]=1;
ddp[n][a[n]]=1;
dp[1][a[1]]=1;
for (int i=2;i<=n;i++)
{
dp[i][a[i]]=1;
for (int t=1023;t>=0;t--)
{
int x=t^a[i];
dp[i][x]+=dp[i-1][t]; //用上当前项
dp[i][t]+=dp[i-1][t]; //不用当前项
dp[i][x]%=mod;
dp[i][t]%=mod;
}
}
for (int i=n-1;i>=1;i--)
{
dpp[i][a[i]]=1;
ddp[i][a[i]]=1;
for (int t=1023;t>=0;t--)
{
int x=t&a[i];
ddp[i][x]+=dpp[i+1][t]; //用上当前项,由前面所有组合情况推出
dpp[i][x]+=dpp[i+1][t]; //用上当前项
dpp[i][t]+=dpp[i+1][t]; //不用当前项
ddp[i][x]%=mod;
dpp[i][x]%=mod;
dpp[i][t]%=mod;
}
}
long long int ans=0;
for (int i=1;i<n;i++)
{
for (int t=0;t<=1023;t++)
{
ans+=dp[i][t]*ddp[i+1][t];
ans%=mod;
}
}
cout<<ans<<endl;
}
}