第一行一个整数 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; }
例二:
传送门
