题意:
给你一个a数组,让你求下式的值
(a1+a2)⊕(a1+a3)⊕…⊕(a1+an)
⊕(a2+a3)⊕…⊕(a2+an)
…
⊕(an−1+an)
题解:
按二进制每一位来处理
对于当前位p,只有a[i]+a[j],两数中只有一个数在当前位为1的情况下,两数相加这一位为1.
sum记录a[]中在当前位有1的个数,有sum*(n-sum)个(i,j)对数,由该式得sum必须为奇数,因为偶数乘任何数还是还是偶数,
n-sum也必须是奇数,所以满足 (sum&1)&&((n-1)&1),ans^=p;
另外考虑进上来的1,比如01,01,第二位没有1,但最后这两数相加第二位是1,是因为,第一位两个1进上来了。
根据b[i]&(p-1) 生成b数组,然后从小到大sort
如果b[i]+b[pos]<b,b[i]+b[pos+1]>=b,那么pos后面的与b[i]相加全部大于等于b,该位又多了(n-pos)个1
最后在判断下当前1的个数sum是否为奇数就行。
#include<bits/stdc++.h>
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
using namespace std;
const double eps=1e-8;
typedef long long ll;
const int maxn = 400050;
int a[maxn],b[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int ans=0;
for(int p=1;p<=20000000;p<<=1){
for(int i=1;i<=n;i++) b[i]=a[i]&(p-1);
int sum=0;
for(int i=1;i<=n;i++){
if((a[i]&p)){
sum++;
}
}
if((sum&1)&&((n-1)&1)) ans^=p;
sort(b+1,b+1+n);
int pos=n;
sum=0;
for(int i=1;i<=n;i++){
pos=max(pos,i);
for(;pos>i&&(b[pos]+b[i])>=p;pos--);
sum^=(n-pos);
}
if(sum&1) ans^=p;
}
printf("%d\n",ans);
}