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; }