第一行一個整數 n ,代表數列長度。
第二行 n 個整數,代表數列。
輸出描述:
輸出一個整數,代表答案。
示例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<map> #include<string> #include <math.h> #include<memory.h> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; int read() { int x = 0, f = 1; char s; while((s = getchar()) > '9' || s < '0') {if(s == '-') f = -1;} while(s <= '9' && s >= '0') { x = (x << 1) + (x << 3) + (s ^ 48); s = getchar(); } 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 map<int,int>mp; ll a[maxn]; ll b[maxn]; int main(){ int n; cin>>n; ll ans=0; for(int i=1;i<=n;i++){ cin>>a[i]; b[i]=b[i-1]^a[i]; if(b[i]==0){ ans++; } ans+=mp[b[i]]; mp[b[i]]++; } cout<<ans<<endl; }
例二:
傳送門
