题目链接
思路:求出前缀异或和, 枚举所有以i结尾的区间值,对后面以i+1开头的区间值数量求和。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int MAXN = 1e3+10;
int a[MAXN];
int sum[MAXN];
LL c[1000005];
int main()
{
int n;
while(~scanf("%d", &n))
{
LL ans=0;
sum[0]=0;
memset(c, 0, sizeof(c));
for(int i=1;i<=n;++i)
{
scanf("%d", &a[i]);
sum[i]=sum[i-1]^a[i];
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=i;++j)
c[sum[i]^sum[j-1]]++;
for(int j=i+1;j<=n;++j)
ans+=c[sum[i]^sum[j]];
}
printf("%lld\n", ans);
}
return 0;
}
思路二:
存下所有以i开头j结尾的异或和,sort一下,二分查找区间的界限位置。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int MAXN = 1e3+10;
int a[MAXN];
struct node{
int num, l, r;
}b[1000005];
bool cmp(node a, node b)
{
if(a.num!=b.num)
return a.num<b.num;
if(a.l!=b.l)
return a.l<b.l;
if(a.r!=b.r)
return a.r<b.r;
return false;
}
int binary_search1(int l, int r, int cur)
{
int ans=-1, mid;
while(l<=r)
{
mid=(l+r)>>1;
if(b[mid].num==b[cur].num)
{
if(b[mid].l>b[cur].r)
r=mid-1, ans=mid;
else
l=mid+1;
}
else if(b[mid].num>b[cur].num)
r=mid-1;
else
l=mid+1;
}
return ans;
}
int binary_search2(int l, int r, int cur)
{
int ans=-1, mid;
while(l<=r)
{
mid=(l+r)>>1;
if(b[cur].num<b[mid].num)
{
r=mid-1;
ans=mid;
}
else
l=mid+1;
}
return ans;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i=1;i<=n;++i)
scanf("%d", &a[i]);
int cnt=1;
for(int i=1;i<=n;++i)
{
int tmp=0;
for(int j=i;j<=n;++j)
{
tmp^=a[j];
b[cnt].num=tmp;
b[cnt].l=i;
b[cnt].r=j;
cnt++;
}
}
LL ans=0;
sort(b+1, b+cnt,cmp);
for(int i=1;i<cnt;++i)
{
int l, r;
l=binary_search1(1,cnt-1, i);
r=binary_search2(1,cnt-1, i);
//printf("%d %d\n", l, r);
if(l==-1)
continue;
else
{
if(r==-1)
r=cnt;
ans+=r-l;
}
}
printf("%lld\n", ans);
}
return 0;
}