2020牛客寒假算法基础集训营4D.子段异或(位运算)

链接:https://ac.nowcoder.com/acm/contest/3005/D

 

题意:

给一个数组,问有多少个子序列的异或和为0

思路:

首先我们需要一个定义一个前缀和数组sum[i],代表从1到i这段的异或和

那么神奇的事情来了,sum[l-r]=sum[l-1]^sum[r],因为他们相同的部分异或起来为0,这也是与普通前缀和不同的部分

如果这段的异或和为0,那么sum[l-1]^sum[r]=0,也就是sum[l-1]=sum[r],因此我们只需要统计每个前缀和的数值,看有多少前缀和相同

最后答案就为∑cnti*(cnti-1)

#include<iostream>
#include<algorithm>
#include<map>
 using namespace std;
 const int maxn=2e5+10;
 typedef long long ll;
 ll a[maxn];
 map<ll,ll> s;
 int main()
 {
     ll ans=0,n,sum=0;
     cin>>n;
     s[0]=1;
     for(int i=1;i<=n;i++){
         scanf("%lld",&a[i]);
         sum^=a[i];
         ans+=s[sum];
         s[sum]+=1;
     }
    cout<<ans<<endl;
    return 0;
 }

 

posted @ 2020-02-12 17:35  overrate_wsj  阅读(137)  评论(0编辑  收藏  举报