题意:
求n个数中两两和的异或。
思路:
逐位考虑,第k位只需考虑0~k-1位,可通过&(2k+1-1)得到一组新数。
将新数排序,当两数和在[2k,2k+1)和[2k+1+2k,2k+2)之间时该位为1,又因为两数的最大和为2*(2k+1-1)=2k+2-2,
即当两数和在[2k,2k+1)和[2k+1+2k,2k+2-2]之间时该位为1。
对于每个数,找到和
大于等于2k
小于2k+1
大于等于2k+1+2k
的三个临界点(因为两数之和一定小于等于2k+2-2,所以第四个临界点可以忽略),
位于它们间的数与该数的和在第k位即为1,统计1的个数,该位异或偶数次后为0,异或奇数次后为1。
Tips:
调试了半天发现少加了一对括号,以后还是不要猜优先级了。
#include <bits/stdc++.h> using namespace std; const int MAX_N=1e6; int n,ans; int a[MAX_N],b[MAX_N]; int main() { cin>>n; for(int i=0;i<n;i++) cin>>a[i]; for(int k=0;k<25;k++){ for(int i=0;i<n;i++) b[i]=a[i]&((1<<(k+1))-1); sort(b,b+n); int d=1<<k; int cnt=0; for(int i=n-1,x=0,y=0,z=0;i>=0;i--){ while(x<n&&b[x]+b[i]<d) x++; while(y<n&&b[y]+b[i]<2*d) y++; while(z<n&&b[z]+b[i]<3*d) z++; cnt+=max(0,min(i,y)-x); cnt+=max(0,i-z); } if(cnt&1) ans|=1<<k; } cout<<ans<<endl; return 0; }