其他分享
首页 > 其他分享> > 子数组异或和

子数组异或和

作者:互联网

子数组异或和

题目链接: https://www.acwing.com/problem/content/4510/

其他相关题解点这里

思路

异或俗称“不进位加法”.

如果x = y则有x ^ y = 0

这个题根据这个性质来写

首先预处理前缀异或和数组s[]

然后找哪个一段区间异或和为0,并且数量为偶数个

即区间(i,j]([i+1,j]),s[i] ^ s[j] = 0i - j为偶数

等价于在[0,i-1]中找一个s[j],它和s[i]的值相等,并且使得i - j为偶数.

image

查找一个值出现的次数,可以用哈希表来存(出现的次数),这样可以使得查找时间复杂度为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