题意:
给出两个长度为N的序列A,B,求:
(A1+B1)?(A1+B2)?(A1+B3)?……?(A2+B1)?(A2+B2)?(A2+B3)?……?(An+Bn)(A1+B1)?(A1+B2)?(A1+B3)?……?(A2+B1)?(A2+B2)?(A2+B3)?……?(An+Bn)
分析:
首先,主要的方法还是构造,如果我们要求答案的二进制下第kk位,那么很显然的一点是,A与B中所有高于第
位的部分一定对这一位的答案无任何影响,所以我们将所有数全部模2k+12k+1。
再来观察所有数的和中,第kk位为1的数的特点:设该数为
,
则必然满足2k≤x<2×2k或3×2k≤x<4×2k2k≤x<2×2k或3×2k≤x<4×2k。
证明很显然,因为每个数都严格小与2k+12k+1,所以相加之和必然小于2×2k+12×2k+1,在这类数中,若二进制下第kk位为1,则其必然大于等于
,但大于等于2k2k中也有一部分数的第k位为0的。即第k+1k+1位为1,第kk位为0。这种数必然在
之间
所以,我们只需要将所有数取模后,将b数列排序,a数列依次取出一个数(ai)(ai),求出在另一个数列中值在[2k?ai,2×2k?ai)与[3×2k?ai,4×2k?ai)[2k?ai,2×2k?ai)与[3×2k?ai,4×2k?ai)内的数的个数即可。具体方法可以用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);
}