题意:给你一些数,分成2个集合,左边的集合的所有数必定在右边集合所有数的左边,然后左边集合求异或值,右边集合求AND值,要求是2个集合的值要一样,求所有集合数。
题解说是简单题。。当时想了好久都没想出来。。。
方法就是开2个二维数组,分别保存从前往后的到第i个所能获得所有的j值,以及从后往前到第i个所能获得的所有的j值,然后最后计算的时候只需要2层循环遍历一遍n和1024,不能简单的2者相乘,因为这样必定会出现重复的集合,正确的做法是要用选择第i个所能到达的j值的个数乘上后面所有能到达j值的个数,那么前者就是dp[i][j] - dp[i-1][j]。切记!做的时候记得要把前面写的加上MOD再去取模,不然可能会出现负数。血的教训。。
AC代码:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<ctime>
using namespace std;
#define ll __int64
#define MOD 1000000007
ll x[1005][1030],y[1005][1030];
int a[1005];
int main()
{
//freopen("input.txt","r",stdin);
int i,j,t,n;
scanf("%d",&t);
while(t--)
{
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
scanf("%d",&n);
for(i = 1; i <= n; i++) scanf("%d",&a[i]);
for(i = 1; i <= n; i++)
{
x[i][a[i]]++;
for(j = 0; j < 1024; j++) if(x[i-1][j])
{
x[i][j] += x[i-1][j];
x[i][j] %= MOD;
x[i][j^a[i]] += x[i-1][j];
x[i][j^a[i]] %= MOD;
}
}
for(i = n; i >= 1; i--)
{
y[i][a[i]]++;
for(j = 0; j < 1024; j++) if(y[i+1][j])
{
y[i][j] += y[i+1][j];
y[i][j] %= MOD;
y[i][j&a[i]] += y[i+1][j];
y[i][j&a[i]] %= MOD;
}
}
ll ans = 0;
for(i = 1; i < n; i++)
for(j = 0; j < 1024; j++)
ans = (((x[i][j]-x[i-1][j]+MOD)%MOD*y[i+1][j])%MOD+ans)%MOD;
printf("%I64d\n",ans);
}
return 0;
}