1.异或运算基本性质
1. 异或运算满足交换律和结合律:a^b^c = a^c^b
2. 任何数和0进行异或运算,结果还是这个数本身:a^0 = a
3. 任何数和自身进行异或运算,结果是0:a^a = 0
4. 异或运算是可逆的,即对一个数进行两次异或同一个数,结果还是这个数本身:a^b^b = a
2.题目链接
https://www.luogu.com.cn/problem/P9236
3.解题思路
对于题目要求出区间异或的和,我们可以利用前缀和,再根据上面所说的性质,我们可以推出:
但是如果说单纯利用前缀和的话,时间复杂度过高,所以我们需要另辟蹊径。
我们可以采用二进制的思想将数的每一位进行分解,如果此区间所有数这一位异或值等于1,那么也就可以说明此区间对答案有贡献,然后乘上对应权值就是其实际贡献。但是对于这一道题,计算所有区间的异或和,也就是说这里面每一个数都必定两两异或 ,由乘法定理,故可以得出总和为:
4.奉上代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5;
LL sum=0;
LL s[N];
LL w[N][2];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]^=s[i-1];
}
for(int i=0;i<=n;i++)
for(int j=0;j<=20;j++)
w[j][(s[i]>>j)&1]++;
for(int i=0;i<=20;i++)
sum+=w[i][0]*w[i][1]*pow(2,i);
cout<<sum;
return 0;
}