链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
给定一个长度为n的整数数组,问有多少对互不重叠的非空区间,使得两个区间内的数的异或和为0。
从这道题中我们可以知道,前缀和与前缀异或和(ps:异或和就是全部异或起来,而不是异或后再求和)具有相似的性质,如:a[1]~a[i]前缀异或和为b[i](a[i]=a[i-1]^a[i]),a[1]~a[j]前缀异或和为b[j](a[j]=a[j-1]^a[j]),i<j,则区间[i+1,j]的前缀异或和为b[j]^b[i]。
对于此题,我们不妨以i为基准点,依次遍历1~i的前缀异或和,并将结果存入一特定数组,再遍历i~n的前缀异或和,将查询到的之前存在过的前缀异或和进行累次异或,累其结果便是答案(值都一样了,说明异或起来肯定为0)。至于为何这样不重不漏,可以想:1、分界点是不断变动的;2、每个分界点所决定的区间由于有不重不漏的条件限制,所以只存在于之前讨论的区间取值。
上代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const ll maxx=1005;
const ll inf=20000000005;
ll n,cnt,a[maxx],b[10000005];
int main(){
cin>>n;
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
a[i]=a[i-1]^a[i];
}
for(int i=1;i<=n;++i){
for(int j=1;j<=i;++j) b[a[i]^a[j-1]]++;
for(int j=i+1;j<=n;++j) cnt+=b[a[i]^a[j]];
}
cout<<cnt;
return 0;
}