题意:给定一个数组a,求
(a1+a2)⊕(a1+a3)⊕…⊕(a1+an)⊕
(a2+a3)⊕…⊕(a2+an)
…⊕(an−1+an)
n<=4e5
思考:显然是思考位运算,一位一位去考虑。我们可以发现,第i位只有拥有奇数个数的1时才可以产生贡献。那么我们就考虑产生1的情况。
1)第i-1位没有进位时,若第i位为1,则统计其他数字第i位为0的情况
2)第i-1位没有进位时,若第i位为0,则统计其他数字第i位为1的情况
3)第i-1位进位时,若第i位为1,则统计其他数字第i位为1的情况
4)第i-1位进位时,若第i位为0,则统计其他数字第i位为0的情况
同时考虑不能重复,所以枚举时要稍加注意。
考虑每一位,每一位去排序一遍,则复杂度为O(30*n*logn)
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pb push_back
#define sz size
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
#define endl "\n"
const ll inf=1ll<<60;
const int mod=998244353;
mt19937 rnd(std::chrono::system_clock::now().time_since_epoch().count());
//uniform_int_distribution<long long> dist(0, 100000);//随机数限定范围:dist(rnd);
const int N=400010;
int n,a[N],suf1[N],suf0[N],g[N];
array<int,2> b[N];
inline int high(int x,int y){
return ((x>>y)&1);
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int ans=0;
for(int bit=1;bit<=30;bit++){
int mask=1<<(bit-1);
for(int i=1;i<=n;i++){
b[i]={(a[i]&(mask-1)),((a[i]>>(bit-1))&1)};
}
sort(b+1,b+n+1);
suf1[0]=suf0[0]=0;
for(int i=1;i<=n;i++){
if(b[i][1])
suf1[i]=suf1[i-1]+1,suf0[i]=suf0[i-1];
else
suf0[i]=suf0[i-1]+1,suf1[i]=suf1[i-1];
}
for(int i=1;i<=n;i++) g[i]=b[i][0];
// for(int i=1;i<=n;i++) cout<<suf0[i]<<" "<<suf1[i]<<" |--->"<<i<<"<---\n";
int cnt=0;
for(int i=1;i<n;i++){
int tmp=lower_bound(g+i+1,g+n+1,mask-g[i])-g;
//不进位
if(b[i][1])cnt+=suf0[tmp-1]-suf0[i];
else cnt+=suf1[tmp-1]-suf1[i];
//进位
if(b[i][1]) cnt+=suf1[n]-suf1[tmp-1];
else cnt+=suf0[n]-suf0[tmp-1];
}
if(cnt%2) ans+=(1<<(bit-1));//cout<<cnt<<"\n";
}
cout<<ans<<"\n";
}
signed main(){
// IOS;
int _test=1,_tot=0;
// cin>>_test;
while(_test--){
// printf("Case #%d: \n",++_tot);
solve();
}
return 0;
}