兩個bit的異或(下文均用^表明異或運算):1^0=1 0^1=1 1^1=0 0^0=0,也就是左右元素不一樣時爲1,相同時爲0。ios
對於兩個int的異或,就是對它的二進制表示的每一位進行異或運算,好比2^5=binary(010^101)=binary(111)=7數組
而且異或運算知足交換律、結合律,即a^b=b^a,a^b^c=(a^b)^c=a^(b^c)spa
異或運算還有性質:x^0=x,x^x=0(這裏能夠得出推論:若x^y=0,則x=y;)3d
OK,到此就能夠分析題目了,題目給出數組a[N]找出全部不重疊區間,區間的數字xor和爲0。code
這裏定義f(i,j)=a[i]^a[i+1]^...^a[j],這裏值得注意的是不重疊區間,那麼假若有一對重疊區間的xor和爲0,那咱們應該選擇哪一組呢?blog
設重疊區間爲[b,c],兩個區間爲[a,c]和[b,d],其中a<=b<c<=d。ci
顯然應該選擇[a,c],由於這樣至關於在[c,N]區間尋找xor和爲0的子區間數量,而c<=d<N,[c,N]是在[d,N]的基礎上多了0個以上數,那麼子區間數量確定很多於[d,N]。it
所以思路就是先找出最左邊的子區間,而後在右邊剩餘區間重複以上操做。io
最左邊也就是區間[a,b]知足b最小,也就是b從0到n,若是找到了一組異或和爲0的區間[a0,b0],那麼b就從b0+1開始,可是a不用從0開始,而是也從a0+1開始。class
由於若存在f(a0,b0+t)=0,那麼易證f(b0+1,b0+t)也爲0,能夠分紅2個異或和爲0的區間。
更詳細的證實就不用說了,有這樣的思路後直接上代碼吧。
#include <iostream> #include <vector> #include <algorithm> using namespace std; void solution(int a[], int n) { int cnt = 0; // 閉區間個數 vector<int> v; v.reserve(n); int low = 0; // 閉區間左邊界的下限(即上一個找到異或和爲0的閉區間右邊界+1) for (int i = 0; i < n; i++) { // 查找以i爲閉區間的右邊界的區間是否存在知足異或和爲0的 v.clear(); // 依次加入a[k]、a[k-1]^a[k]、...、a[low]^a[low+1]^...^a[k] v.push_back(a[i]); for (int j = i - 1; j >= low; j--) { v.push_back(v.back() ^ a[j]); } if (find(v.begin(), v.end(), 0) != v.end()) { // 存在異或和爲0的子區間 cnt++; low = i + 1; // 更新閉區間左邊界, 避免重複查找 } } cout << cnt << endl; } int main() { int n; cin >> n; vector<int> v(n); for (int i = 0; i < n; i++) { cin >> v[i]; } solution(&v[0], n); return 0; }