链接:https://ac.nowcoder.com/acm/contest/3005/D
来源:牛客网
题目描述
输入一个数列a,你需要输出其中异或值为0的不同子段的数量。一个子段 [l,r] (1≤l≤r≤n1 \le l \le r \le n1≤l≤r≤n)的异或值为al⊕al+1⊕al+2⊕…⊕ara_l \oplus a_{l+1} \oplus a_{l+2} \oplus \ldots\oplus a_ral⊕al+1⊕al+2⊕…⊕ar,其中⊕\oplus⊕符号代表异或运算。
两个子段被视为相同的,当且仅当其开始和结束位置均对应相同。
输入描述:
第一行一个整数 n ,代表数列长度。
第二行 n 个整数,代表数列。
输出描述:
输出一个整数,代表答案。
示例1
输入
复制5 1 2 3 2 1
5 1 2 3 2 1
输出
复制2
2
说明
子段 [1,3] 和子段 [3,5] 是合法子段。
备注:
n≤200000,0≤ai≤230−1n \le 200000, 0 \le a_i \le 2^{30}-1n≤200000,0≤ai≤230−1
题解:
这个题不会做,当场还查找了异或的性质,发现异或的确有独特的优化方式。。。。。但是本题重点在于鸽巢原理的理解
先贴代码:
#include <bits/stdc++.h>
using namespace std;
map<int,int> mp;
int n;
long long res;
int main(){
scanf("%d",&n);
mp[0]=1;
int tem=0;
for(int i=0;i<n;i++){
int k;
scanf("%d",&k);
tem^=k;
if(mp[tem]){
res+=mp[tem];
mp[tem]++;
}else{
mp[tem]=1;
}
}
printf("%lld\n",res);
return 0;
}
分析:
看到区间异或和就想起来了前缀。