题目链接:hdu 4901 The Romantic Hero
题目大意:给定一个序列,要求选出两个集合,S和T,要求S中选中的元素的下标都要小于T中元素的下标。
而且说S中元素的亦或和要等于T中元素取且的和。
解题思路:dp, 思路非常好想。就是细节比較恶心。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef __int64 ll;
const int maxn = 1024;
const ll MOD = 1e9+7;
int n, num[maxn];
ll l[maxn][maxn+10][2], r[maxn][maxn+10];
void init () {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &num[i]);
}
ll solve () {
memset(l, 0, sizeof(l));
memset(r, 0, sizeof(r));
for (int i = 1; i < n; i++) {
l[i][num[i]][1]++;
for (int j = 0; j < maxn; j++) {
l[i+1][j][1] = (l[i][j^num[i+1]][1] + l[i][j^num[i+1]][0]) % MOD;
l[i+1][j][0] = (l[i][j][1] + l[i][j][0]) % MOD;
}
}
for (int i = n; i; i--) {
r[i][num[i]]++;
for (int j = 0; j < maxn; j++) {
r[i-1][j] = (r[i-1][j] + r[i][j]) % MOD;
r[i-1][j&num[i-1]] = (r[i-1][j&num[i-1]] + r[i][j]) % MOD;
}
}
ll ans = 0;
for (int i = 1; i < n; i++) {
for (int j = 0; j < maxn; j++) {
/*
if (l[i][j] * r[i+1][j])
printf("%d %d %lld %lld
", i, j, l[i][j], r[i+1][j]);
*/
ans = (ans + l[i][j][1] * r[i+1][j] % MOD) % MOD;
}
}
return ans;
}
int main () {
int cas;
scanf("%d", &cas);
while (cas--) {
init();
printf("%I64d
", solve());
}
return 0;
}