异或前缀和,组合数学——cf1054D
/* 每个异或前缀和sum[i]只有两个值 区间异或和不为0,即两个不相等的前缀和 sum[i]的两个前缀和只要标记一个就可以了,为了去重只用map保存最小的那个来计数 最后统计相同的前缀和时,为了使相同的最小,每个map的值要平分 */ #include<bits/stdc++.h> using namespace std; #define ll long long #define maxn 200005 map<ll,ll>mp; map<ll,ll>::iterator it; ll k,n,a[maxn],sum[maxn]; int main(){ cin>>n>>k; mp[0]++;//0的情况 for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++){ sum[i]=sum[i-1]^a[i]; sum[i]=min(sum[i],sum[i]^((1<<k)-1)); mp[sum[i]]++; } ll ans=n*(n+1)/2;//考虑0的情况 for(it=mp.begin();it!=mp.end();it++){ ll x=it->second,y=x/2; x-=y; ans-=(y-1)*y/2; ans-=(x-1)*x/2; } cout<<ans<<endl; }