题目描述
输入一个数列a,你需要输出其中异或值为0的不同子段的数量。一个子段
的异或值为
,其中
符号代表异或运算。
两个子段被视为相同的,当且仅当其开始和结束位置均对应相同。
输入描述:
第一行一个整数 n ,代表数列长度。
第二行 n 个整数,代表数列。
输出描述:
输出一个整数,代表答案。
输入
5
1 2 3 2 1
输出
2
说明
子段 [1,3] 和子段 [3,5] 是合法子段。
备注:
题解
- 很容易想到记录前缀和,但是记录之后肯定不是暴力 的,我们要考虑如何简化这过程。
- 如果区间 是合法的,那么前缀中
- 那么我们就可以从前到后 求一边异或前缀和,然后对于每个前缀和,从前到后,记录当前异或的结果
- 如果当前结果出现过,那么说明满足上述条件,加上这个前缀和出现过的次数即可。
- 当然既然所有操作之和之前的出现过的情况有关,我们可以将两步操作合并。
AC-Code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 7;
int a[maxn];
int main() {
int n; cin >> n;
ll ans = 0;
int num = 0;
map<int, int> mp;
mp[0] = 1;
for (int i = 0; i < n; i++) {
cin >> a[i];
num ^= a[i]; // 记录前缀和
ans += mp[num]; // 加上之前前缀和是num的次数
mp[num]++; // 次数++
}
cout << ans << endl;
return 0;
}