傳送門
第一行乙個整數 n ,代表數列長度。
第二行 n 個整數,代表數列。
輸出乙個整數,代表答案。示例1
複製
5複製1 2 3 2 1
2
子段 [1,3] 和子段 [3,5] 是合法子段。意思就是給你乙個子串,問有多少個子串異或和為0 解析:就是先知道乙個知識就是如果x^y==0,則x==y首先你得知道乙個知識點就是:如果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]
。
設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的異或...