題目描述
給定一個大小為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 }
-