题意:
给出两个长度N相同的整数序列A和B,有N^2种方式从A中选择一个数Ai,从B中选择一个数Bj,让两个数相加,求这N^2个数的XOR,即异或。
思路:
暴力的求显然是会超时的,因为是异或,就考虑在最后的结果中以二进制表示每一位是0还是1。
在计算第i位是否为1的时候,显然不需要考虑更高位的影响,那么假设T = 2 ^ i,就将A和B中的每一个数对2T求余。
然后,只有以下两种情况可以满足第i位为1:
T <= Ai + Bj < 2T;
3T <= Ai + Bj < 4T.
将B排序之后,对于每一个Ai,第一种情况和第二种情况,都可以找到Bj对应的区间,善用lower_bound。如果两个区间长度加起来为奇数,那么这一位就是1。
一定用long long。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 using namespace std; 6 7 const int N = 200005; 8 9 long long a[N],b[N]; 10 long long c[N],d[N]; 11 12 bool f[35]; 13 14 int main() 15 { 16 int n; 17 18 scanf("%d",&n); 19 20 for (int i = 0;i < n;i++) 21 { 22 scanf("%lld",&a[i]); 23 } 24 25 for (int i = 0;i < n;i++) 26 { 27 scanf("%lld",&b[i]); 28 } 29 30 for (int i = 0;i <= 30;i++) 31 { 32 long long t = ((long long)1 << i); 33 34 for (int j = 0;j < n;j++) 35 { 36 c[j] = a[j] % (2 * t); 37 d[j] = b[j] % (2 * t); 38 } 39 40 sort(d,d+n); 41 42 for (int j = 0;j < n;j++) 43 { 44 long long y = 2 * t - c[j]; 45 long long x = t - c[j]; 46 47 int p1 = lower_bound(d,d+n,x) - d; 48 int p2 = lower_bound(d,d+n,y) - d; 49 50 if (d[p2] >= y) p2--; 51 if (p2 >= n) p2--; 52 //if (p1 >= n) p1--; 53 54 if (p2 >= p1 && (p2 - p1 + 1) % 2) f[i] = !f[i]; 55 56 y = 4 * t - c[j]; 57 x = 3 * t - c[j]; 58 59 p1 = lower_bound(d,d+n,x) - d; 60 p2 = lower_bound(d,d+n,y) - d; 61 62 if (d[p2] >= y) p2--; 63 if (p2 >= n) p2--; 64 //if (p1 >= n) p1--; 65 66 if (p2 >= p1 && (p2 - p1 + 1) % 2) f[i] = !f[i]; 67 } 68 } 69 70 long long ans = 0; 71 72 for (int i = 0;i <= 30;i++) 73 { 74 if (f[i]) ans |= ((long long)1 << i); 75 } 76 77 printf("%lld ",ans); 78 79 return 0; 80 }