[ARC092D] Two Sequences
Time Limit: 3 sec / Memory Limit: 256 MB
难度:\(4.0\)
-
Problem Statement
You are given two integer sequences, each of length \(N\): \(a_1, \cdots ,a_N\) and \(b_1, \cdots ,b_N\).
There are \(N^2\) ways to choose two integers \(i\) and \(j\) such that \(1 \leq i,j \leq N\). For each of these \(N^2\) pairs, we will compute \(a_i+b_j\) and write it on a sheet of paper. That is, we will write \(N^2\) integers in total.
Compute the XOR of these \(N^2\) integers.
给定两个长度为 \(n\) 的正整数数组 \(a,b\) ,求 \(\forall 1 \leq i,j \leq n\),\(a_i+b_j\) 在二进制下的异或和 。
-
Input
\(n\) 和两数组 \(a,b\) 。
-
Output
答案。
-
Sample Input
1 2 3 |
5 1 2 3 4 5 1 2 3 4 5 |
-
Sample Output
1 |
2 |
-
Constraints
\(1 \leq n \leq 200000\),\(1 \leq a_i,b_j \leq 2^{28}\)。
Source:ARC092D
from orz zzx:
对每一位 \(d\),求有多少对 \(i,j\) 满足 \(a_i+b_j\) 的第 \(d\) 位为 \(1\),也就是 \((a_i+b_j) \bmod 2d+1 \geq 2d\),单调性扫一扫就行了,复杂度 \(O(n(\log a_i+\log b_i))\)。
这题比我在泉州集训出的某个题略微简单一点,那个题是求所有 \(l \leq r\)
的 \(\sum\limits_{i=l}^r a_i\) 的异或和,思路类似。
from sb mnihyc:
「单调性扫一扫」想得不是很清楚的可以直接排序+二分。
具体来说就是:枚举位,要查找序列中有多少个数当前位为 \(1\)。
如果要查找 \(N\) 次的话,普通查找的复杂度就是 \(N^2\)。
显然我们可以通过排序优化这个操作。
将其中一个数组排序后再查找,目标就变成了有序序列中连续的单调的一段,使用二分,复杂度 \(O(n \log n)\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#include <cstdio> #include <cstdlib> #include <cstring> #include <climits> #include <algorithm> #define _max(_a_,_b_) ((_a_)>(_b_)?(_a_):(_b_)) #ifdef ONLINE_JUDGE char __B[1<<15],*__S=__B,*__T=__B; #define getchar() (__S==__T&&(__T=(__S=__B)+fread(__B,1,1<<15,stdin),__S==__T)?EOF:*__S++) #endif inline int getnum() { register char c=0; while(!(c>='0' && c<='9')) c=getchar(); register int a=0; while(c>='0' && c<='9') a=a*10+c-'0',c=getchar(); return a; } int a[205050],b[205050]; #define GetLen(_arr,_l,_r) (std::lower_bound(&(_arr)[1],&(_arr)[N+1],_r)-std::lower_bound(&(_arr)[1],&(_arr)[N+1],_l)) int ta[205050],tb[205050]; int main() { register int N=getnum(),mxv=0; for(register int i=1;i<=N;i++) a[i]=getnum(),mxv=_max(mxv,a[i]); for(register int i=1;i<=N;i++) b[i]=getnum(),mxv=_max(mxv,b[i]); register unsigned dig=1; while(mxv) dig++,mxv>>=1; int ans=0,pw2=1; while(dig--) { for(register int i=1;i<=N;i++) ta[i]=a[i]&((pw2<<1)-1),tb[i]=b[i]&((pw2<<1)-1); std::sort(&tb[1],&tb[N+1]); register bool sum=0; for(register int i=1;i<=N;i++) sum^=GetLen(tb,pw2-ta[i],(pw2<<1)-ta[i])&1, sum^=GetLen(tb,pw2+(pw2<<1)-ta[i],(pw2<<2)-ta[i])&1; ans|=pw2*sum,pw2<<=1; } printf("%d\n",ans); return 0; } |