子数组异或和
作者:互联网
子数组异或和
题目链接: https://www.acwing.com/problem/content/4510/
思路
异或
俗称“不进位加法”.
如果x = y
则有x ^ y = 0
这个题根据这个性质来写
首先预处理前缀异或和数组s[]
然后找哪个一段区间异或和为0,并且数量为偶数个
即区间(i,j]
([i+1,j]
),s[i] ^ s[j] = 0
且i - j
为偶数
等价于在[0,i-1]
中找一个s[j]
,它和s[i]
的值相等,并且使得i - j
为偶数.
查找一个值出现的次数,可以用哈希表来存(出现的次数),这样可以使得查找时间复杂度为O(1),要求i-j为偶数,可以将前缀异或和分奇数偶数下标来存到哈希表中,这样查找的时候只需判断i为奇数还是偶数即可.
代码
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
LL a[N];
int main()
{
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i ++) scanf("%lld",&a[i]);
unordered_map<int,int> h[2]; // 要开两个哈希表,一个存奇数,一个存偶数
LL res = 0;
LL sum = 0; // 前缀异或和
h[0][sum] ++; // 将偶数前缀和s[0]存入
for(int i = 1; i <= n; i ++)
{
sum = sum ^ a[i];
res += h[i % 2][sum]; // i为偶数 前缀和存到h[0]中,奇数存到h[1]中
h[i % 2][sum] ++;
}
printf("%lld",res);
return 0;
}
标签:前缀,int,LL,偶数,异或,数组,include 来源: https://www.cnblogs.com/rdisheng/p/16584587.html