https://ac.nowcoder.com/acm/contest/3005/D
题目描述
输入一个数列a,你需要输出其中异或值为0的不同子段的数量。一个子段的异或和
其中
符号表示异或。两个子段被视为相同的,当且仅当其开始和结束位置均对应相同。
思路
考虑它的前缀和,如果区间异或和为0,那么它和前面所有所有的异或和为0的连续的区间异或依然为0,如果前缀和
,前缀和
,说明
到
中有一段为0,所以只需要从头计算前缀和,并且把每一个前缀和出现的次数记录下来,在计算当前位置的前缀和的时候,如果前面有k个和这个位置相同的前缀和,说明他可以和前面k个不同连续区间组成为0的子段。
#include <bits/stdc++.h>
#pragma warning (disable:6031)
#pragma warning (disable:4996)
#define mem(a, b) memset(a, b, sizeof a);
using namespace std;
const int N = 200100;
typedef long long ll;
int n;
int a[N];
ll f[N];
int main()
{
scanf("%d", &n);
ll res = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
ll temp = 0;
map<ll, ll> s;
s.clear();
for (int i = 1; i <= n; i++) {
temp ^= a[i];
if (temp == 0)++res;
if (s[temp]) {
res += s[temp];
}
s[temp]++;
}
printf("%lld\n", res);
return 0;
}