子段異或(異或字首和)

2022-06-09 02:21:12 字數 3594 閱讀 4150

傳送門

第一行乙個整數 n ,代表數列長度。

第二行 n 個整數,代表數列。

輸出乙個整數,代表答案。
示例1

複製

5

1 2 3 2 1

複製

2

子段 [1,3] 和子段 [3,5] 是合法子段。

首先你得知道乙個知識點就是:如果sum[i]為陣列a的前i項的異或和,就是說sum[i]=a[1]^a[2]^a[3]^----a[i]

那麼就有l<=r<=i,sum[l]^sum[l+1]^sum[l+2]^sum[l+3]------^sum[r]=sum[r]^sum[l-1]

意思就是給你乙個子串,問有多少個子串異或和為0

解析:就是先知道乙個知識就是如果x^y==0,則x==y

設b[i]為異或字首和,則

b[i] = a[1] ^ a[2] ^ ... ^ a[i - 1] ^ a[i]

那麼對於一段[1,r]來說,異或字首和為

b[r]

,那麼如果想要以

r結尾的異或為

0的子段的右半部分,

那麼只需要前面出現過乙個數b[i] == b[r],那麼

[i + 1,r]

這一段異或和為

0

就是:如果在r的前面出現乙個

i,使得

b[i]==b[r]

則i+1到r

的異或和為

0

#include#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;

intread()

while(s <= '

9' && s >= '0'

)

return x *f;

}const

int inf=0x3f3f3f3f

;const

int maxn=1e6+122;//

子段異或和為0

//設b[r]為他的異或字首和

//有b[r]==b[1]^b[2]......^b[r]

//如果在前面出現乙個b[i]==b[r]則i+1到r的異或和為0

mapmp;

ll a[maxn];

ll b[maxn];

intmain()

ans+=mp[b[i]];

mp[b[i]]++;

}cout

}

例二:傳送門

題目大意:

給你乙個數列 求有多少區間滿足

1 長度為偶數

2 前一半異或值等於後一半異或值

思路

前一半異或值等於後一半異或值 那麼這個區間異或值為0 只需找字首異或相等且長度為偶數即可

#include#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;

intread()

while(s <= '

9' && s >= '0'

)

return x *f;

}const

int inf=0x3f3f3f3f

;const

int maxn=5e6+100

;ll a[maxn];

ll b[maxn];

ll dp[maxn][2];

intmain()

ll ans=0

;

for(int i=1;i<=n;i++)

ans+=dp[b[i]][i%2

]; dp[b[i]][i%2]++;

} cout

}

D 子段異或

輸入乙個數列a,你需要輸出其中異或值為0的不同子段的數量。乙個子段 l,r 1 le l le r le n1 l r n 的異或值為a l oplus a oplus a oplus ldots oplus a ral al 1 al 2 ar 其中 oplus 符號代表異或運算。兩個子段被視為相...

異或字首和 夢境

題目描述 相信你也和 oier kry 一樣,碼了幾行 就輕鬆搞定其等價電阻的值。kry 忽然間意識到不能總是不幹正經事,聯賽馬上就來了,該整理下 u 盤,好好複習總結下,於是 插上 u 盤,開始翻閱以前學習的資料。由於前面的更換教室地板,再加上剛才解決電路連線問題,kry 有點累了,不知道 來的睏...

HDU 5968 異或密碼 字首異或

給出乙個長為n的陣列a,給出m個質詢,每個質詢給出乙個數字,需要找到序列a中所有連續子串行的異或結果中與質詢數字差的絕對值最小的乙個,輸出最長的這種連續子串行的長度 異或字首和 暴力 我們知道乙個數異或自己即抵消異或效果 比如a b a b a a b b 那麼我們存下字首和之後,想要求i j的異或...