Problem Statement
You are given two integer sequences, each of length N: a1,…,aN and b1,…,bN.
There are N2 ways to choose two integers i and j such that 1≤i,j≤N. For each of these N2 pairs, we will compute ai+bj and write it on a sheet of paper. That is, we will write N2 integers in total.
Compute the XOR of these N2 integers.
Definition of XOR
Constraints
- All input values are integers.
- 1≤N≤200,000
- 0≤ai,bi<228
Input
Input is given from Standard Input in the following format:
N a1 a2 … aN b1 b2 … bN
Output
Print the result of the computation.
Sample Input 1
2 1 2 3 4
Sample Output 1
2
On the sheet, the following four integers will be written: 4(1+3),5(1+4),5(2+3)and 6(2+4).
Sample Input 2
6 4 6 0 0 3 3 0 5 6 5 0 3
Sample Output 2
8
Sample Input 3
5 1 2 3 4 5 1 2 3 4 5
Sample Output 3
2
Sample Input 4
1 0 0
Sample Output 4
0
题意:
给你两个含有n个数的数组a,b
然后我们对每一个a[i] 加上 b[j] 得到的数,把这些数全部异或起来,问最后的异或值是多少?
思路:
首先我们对每一个数进行二进制拆分,对每一位进行讨论,
只需要讨论二进制的第x位,在所有相加出来得到的数中是奇数个还是偶数个,
如果是奇数个就对答案有贡献,贡献值为 1<<x,偶数个就没有贡献。
然后问题转化为 我们要咋知道 有多少对 a[i] + b[j] 的第x位为1
由于我们每一步只讨论a[i]+b[j] 的第x位,我们可以只看a[i] 和 b[j] 的 二进制后 x 位,
因为我们只需要考虑 x位的情况就知道了 a[i]+b[j] 的 第x位情况,
那么我们在枚举第x位的时候,把a,b数组对 2的x+1次方 取模 ,即可得到每个数的二进制后x位。
然后利用这个结论,
对于一对数 a[i] +b[j] = num, 如果我们想要num的二进制第x位为1,需要满足:
num <= a[i]+b[j] <2*num
3*num <= a[i]+b[j] < 4*num
这样我们就可以在每一次取模后的数组,对其中一个数组进行排序,然后利用二分找到满足条件的区间,
通过区间的长度相加以来判定最终的满足x位是1的数量的奇偶性,来判定 是否在答案上加上贡献。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d\n",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;} inline void getInt(int* p); const int maxn = 1000010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ int a[maxn]; int b[maxn]; int n; int c[maxn]; int d[maxn]; int main() { //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin); //freopen("D:\\common_text\\code_stream\\out.txt","w",stdout); gbtb; cin >> n; repd(i, 1, n) { cin >> a[i]; } repd(i, 1, n) { cin >> b[i]; } int base = 1; ll ans = 0ll; for (int i = 0; i <= 28; i++) { repd(j, 1, n) { c[j] = a[j] % (2 * base); d[j] = b[j] % (2 * base); } sort(d + 1, d + 1 + n); int num = 0; repd(j, 1, n) { int r = lower_bound(d + 1, d + 1 + n, 2 * base - c[j]) - d - 2; int l = lower_bound(d + 1, d + 1 + n, base - c[j]) - d - 1; num += r - l + 1; r = lower_bound(d + 1, d + 1 + n, 4 * base - c[j]) - d - 2; l = lower_bound(d + 1, d + 1 + n, 3 * base - c[j]) - d - 1; num += r - l + 1; } if (num & 1) { ans += 1ll * base; } base *= 2; } cout << ans << endl; return 0; } inline void getInt(int* p) { char ch; do { ch = getchar(); } while (ch == ' ' || ch == '\n'); if (ch == '-') { *p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 - ch + '0'; } } else { *p = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 + ch - '0'; } } }