題目:傳送門
題意:讓你求

2 <= n <= 400000, 1 <= ai <= 10000000
思路:
對每個二進制位單獨考慮,若答案的第 i 位二進制位是 1,意味着有奇數對 (j, k) 滿足 (aj + ak) 二進制第 i 位是 1.
那么考慮怎么算有多少對 (aj + ak) 滿足二進制第 i 位是1.
高於 i 位的二進制位都不會對答案的第 i 位產生影響,那就把高於 i 位的先去掉,取模一下就可以了,取模后 0 <= ai <= 2^(i + 1) - 1.
那 0 <= aj + ak <= 2^(i + 2) - 2
然后,你 aj + ak 的第 i 位二進制位是 1,那么你可能的區間有 [ 2^i, 2^(i + 1) - 1 ], [ 2^(i + 1) + 2^i, 2^(i + 2) - 2 ]
那你可以枚舉 aj,然后二分一下有多少滿足條件的 ak 就行了。
#include <bits/stdc++.h> #define LL long long #define mem(i, j) memset(i, j, sizeof(i)) #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define pb push_back #define make make_pair #define INF INT_MAX #define inf LLONG_MAX #define PI acos(-1) #define fir first #define sec second using namespace std; const int N = 1e6 + 5; int a[N], b[N]; int main() { int n; scanf("%d", &n); rep(i, 0, n - 1) scanf("%d", &a[i]); int ans = 0; rep(k, 0, 24) { rep(i, 0, n - 1) b[i] = a[i] % (1 << (k + 1)); sort(b, b + n); rep(i, 0, n - 1) { int L = max(0, (1 << k) - b[i]); int R = ((1 << (k + 1)) - 1) - b[i]; int dis = upper_bound(b, b + i, R) - lower_bound(b, b + i, L); if(dis & 1) ans = ans ^ (1 << k); L = max(0, (1 << (k + 1)) + (1 << k) - b[i]); R = ((1 << (k + 2)) - 1) - b[i]; dis = upper_bound(b, b + i, R) - lower_bound(b, b + i, L); if(dis & 1) ans = ans ^ (1 << k); } } printf("%d\n", ans); return 0; }
