题意:
给出两个长度为N的序列A,B,求:
分析:
首先,主要的方法还是构造,如果我们要求答案的二进制下第
k
k
位,那么很显然的一点是,A与B中所有高于第位的部分一定对这一位的答案无任何影响,所以我们将所有数全部模
2k+1
2
k
+
1
。
再来观察所有数的和中,第
k
k
位为1的数的特点:设该数为,
则必然满足
2k≤x<2×2k或3×2k≤x<4×2k
2
k
≤
x
<
2
×
2
k
或
3
×
2
k
≤
x
<
4
×
2
k
。
证明很显然,因为每个数都严格小与
2k+1
2
k
+
1
,所以相加之和必然小于
2×2k+1
2
×
2
k
+
1
,在这类数中,若二进制下第
k
k
位为1,则其必然大于等于,但大于等于
2k
2
k
中也有一部分数的第k位为0的。即第
k+1
k
+
1
位为1,第
k
k
位为0。这种数必然在之间
所以,我们只需要将所有数取模后,将b数列排序,a数列依次取出一个数 (ai) ( a i ) ,求出在另一个数列中值在 [2k−ai,2×2k−ai)与[3×2k−ai,4×2k−ai) [ 2 k − a i , 2 × 2 k − a i ) 与 [ 3 × 2 k − a i , 4 × 2 k − a i ) 内的数的个数即可。具体方法可以用lower_bound
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 200010
using namespace std;
int a[MAXN],b[MAXN],a1[MAXN],b1[MAXN];
int ans,n,sum;
int main(){
SF("%d",&n);
for(int i=0;i<n;i++)
SF("%d",&a[i]);
for(int i=0;i<n;i++)
SF("%d",&b[i]);
for(int i=0;i<29;i++){
for(int j=0;j<n;j++){
a1[j]=a[j]%(1<<(i+1));
b1[j]=b[j]%(1<<(i+1));
}
sort(b1,b1+n);
sum=0;
for(int j=0;j<n;j++){
int s1=lower_bound(b1,b1+n,(1<<i)-a1[j])-b1;
int t1=lower_bound(b1,b1+n,2*(1<<i)-a1[j])-b1;
int s2=lower_bound(b1,b1+n,3*(1<<i)-a1[j])-b1;
int t2=lower_bound(b1,b1+n,4*(1<<i)-a1[j])-b1;
sum+=(t1-s1)+(t2-s2);
}
if(sum&1)
ans+=(1<<i);
}
PF("%d",ans);
}