NC14247
题意
给定一个长度为n的整数数组,问有多少对互不重叠的非空区间,使得两个区间内的数的异或和为0。
1
≤
n
≤
1000
,
0
≤
数
组
元
素
<
100000
1\leq n\leq1000,~~~0\leq数组元素<100000
1≤n≤1000, 0≤数组元素<100000
思路
枚举 预处理异或前缀和
为了便于我们求任意区间的异或和,预处理异或前缀和。
为了避免区间重叠,我们枚举两个区间的分界点
i
i
i,记录
i
i
i(包含)即左边的异或区间值。
我们发现左侧区间扩大,则左边异或区间的贡献会增加的部分为包含扩大位置的连续区间的后缀异或。
eg: 1 2 3 → 1 2 3 4
左侧增加的异或贡献为
[
1
,
4
]
[1,4]
[1,4]
[
2
,
4
]
[2,4]
[2,4]
[
3
,
4
]
[3,4]
[3,4]
[
4
,
4
]
[4,4]
[4,4]
右侧则直接枚举右端点
j
j
j,加入
[
i
+
1
,
j
]
[i+1,j]
[i+1,j]的贡献个数。
这样枚举的右侧区间一定是靠i+1连续的区间,左侧可以不连续。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 1e6 + 5;
const int N = 1e3 + 5;
int n,pre[N],cnt[N];
ll ans;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
int x;cin>>x;
pre[i]=pre[i-1]^x;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++) cnt[pre[i]^pre[j-1]]++;
for(int j=i+1;j<=n;j++) ans+=cnt[pre[j]^pre[i]];
}
cout<<ans<<'\n';
return 0;
}