数论典题,拆成二进制位进行分析,首先用计算异或前缀和,便于区间操作,对于区间[L,R],其区间异或值为 $Xor[L-1]⊕Xor[R]$,统计区间的在第 $i$ 位为$1$的个数,那么根据乘法原理,有$cnt$个$1$和剩余的$0$组合,然后这个是算出了有多少种方案让当前这一位有贡献,要算出答案需要对cnt[i] (n - cnt[i])乘以1 << k - 1(k表示枚举的是二进制下的第几位)
以下介绍两种做法:
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e6+10; int n,s[N],res; signed main(){ cin>>n; for(int i=1;i<=n;i++){ int x; cin>>x; s[i]=s[i-1]^x; } for(int i=0;i<=30;i++){ int cnt=0; for(int j=1;j<=n;j++) if((1<<i)&s[j]) cnt++; res+=(1<<i)*(n-cnt+1)*cnt; } cout<<res; }
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e6+10; int n,s[N],cnt1[N],cnt2[N],res; signed main(){ cin>>n; for(int i=0;i<=30;i++) cnt2[i]=1; for(int i=1;i<=n;i++){ int x; cin>>x; s[i]=s[i-1]^x; for(int j=30;j>=0;j--){ if((1<<j)&s[i]) res+=(1<<j)*cnt2[j],cnt1[j]++; else res+=(1<<j)*cnt1[j],cnt2[j]++; } } cout<<res; }
标签:cnt,Xor,int,long,异或,区间 From: https://www.cnblogs.com/o-Sakurajimamai-o/p/18003562