知识点学习:(还是自己写一遍比较好)
异或和: 子数组的异或和即为子数组中所有元素按位异或得到的结果
通俗解释 例如区间[i,j] 之间的异或和 即为 a[i+1]^a[i+1]^....^a[j+1]
异或是一种基于二进制的位运算,用符号XOR或者 ^ 表示
其运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1 结果用十进位制存储
例如 2^4 -> 二进位就是 10^100 = 110 -> 结果为 6
异或俗称 不进位 加法 具有结合律 交换律
交换律: a^b=b^a
结合律: a^b^c=a^(b^c);
根据异或的性质 我们也可以知道 相同数异或为0 任意数异或0都等于他本身
即 a^a=0 a^0=a
所以 a^b^b=a^0=a;(本题解题关键)
当x=y 时 x^y=0
本题: 可以用存储前缀和的方法存储异或和
异或和: a[i]为前i个数的异或和 a[1]^a[2]^a[3]^...^a[i]
已知: s[l-1]=a[1]^a[2]^a[3]^...^a[l-1]; s[r]=a[1]^a[2]^a[3]^...^a[r];
所以[l,r]区间的异或和为
s[r]^s[l-1]=(a[1]^a[2]^a[3]^...^a[r])^(a[1]^a[2]^a[3]^...^a[l-1])
运用结合律 相同的异或之后为零 其他数异或0都等于他本身
所以s[r]^s[l-1]=s[l]^s[l+1]^...^s[r];
而异或和 数组求得结果 同 前缀和求的方法类似
前缀和 s[i]=s[i-1]+a[i];
异或和 s[i]=a[i]^s[i-1];
本题知识点学习 除了异或和之外
还有 通过哈希表分别存储前n项中奇数偶数 对应的异或和
#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;
const int N=300010;
typedef long long LL;//可以推断 满足条件的连续子数组 会爆int
int n;
int a[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
LL res=0,sum=0;
unordered_map<int,int> h[2];// h[0]是下标为偶数的哈希表,h[1]是下标为奇数的哈希表 储存对应异或和相同的值的数量
h[0][sum]++;
for(int i=1;i<=n;i++)//从前往后遍历 判断前面 与当前异或和值相同值的数量(保证奇偶一致)
//枚举起点和终点(具体可看y总视频) 找到起点和终点相同的数的个数
{
sum^=a[i];// sum 每次异或a[i] 即为求得前i项的异或和
res+=h[i%2][sum];//找到对应异或和相同的数量+1
h[i%2][sum]++;//对应异或和相同的数量+1
}
cout<<res<<endl;
return 0;
}