Xor and Sum(位运算)

题目描述

给定一个大小为N的数组A,第i个元素为Ai。

问有多少的子区间[LR],满足区间数值异或和等于区间数值和,即:

     Al xor Al+1 xor…xor Ar = Al + Al+1 +…+Ar(l+1表示下标)
      a和b的xor即为a和b二进制表示按位取xor得到新数c的十进制表示
5和12的xor计算如下:

510=01012

(12)10=(1100)2

01012xor11002=(1001)2

(1001)2=(9)10

输入

第一行给定一个整数N。
第二行给定N个整数,第i个数即为Ai。
1≤N≤2×10^5
0≤A_i≤2^30

输出

输出满足条件的子区间LR的数量。

样例输入

10
0 0 740 361 473 0 0 826 479 974


样例输出

18

题解:

xor运算可以视为二进制下没有进位的加法,加法运算本身是有进位的加法。

那么可以简单得出这样一个性质:对于一个区间而言,如果异或和加法答案一样,那么把区间缩小答案肯定还是一样;如果异或和加法答案不一样,那么把区间扩大答案肯定还是不一样。

于是我们就可以枚举区间右端点,去寻找最小的左端点,这个区间异或等于区间和,那么以这个区间右端点的合法区间个数就是区间的长度(左端点往里缩都是合法的)。

这个可以预处理出前缀和还有前缀异或和,用双指针维护出来。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<stdio.h>
 4 #include<string.h>
 5 #include<string>
 6 #include<queue>
 7 #include<stdlib.h>
 8 #include<math.h>
 9 #define per(i,a,b) for(int i=a;i<=b;++i)
10 #define rep(i,a,b) for(int i=a;i>=b;--i)
11 #define inf 0xf3f3f3f
12 #define ll long long int 
13 using namespace std;
14 int p[200005];
15 int s[200005];
16 int z[200005];
17 int main()
18 {
19     int m,a;
20     cin>>m;
21     z[0]=0;s[0]=0;
22     per(i,1,m) 
23     {
24         cin>>a;
25         s[i]=s[i-1]+a;
26         z[i]=z[i-1]^a;
27     }
28     ll l=0,sum=0;
29     per(i,1,m)
30     {
31         while((z[i]^z[l])!=(s[i]-s[l])) l++;
32         sum+=i-l;
33     }
34     cout<<sum;
35     return 0;
36 }

-

猜你喜欢

转载自www.cnblogs.com/jiamian/p/12446120.html