Codeforces 1323 D. Present(二进制+二分)_java

题意:

给一个长度为 Codeforces 1323 D. Present(二进制+二分)_java_02 的序列 Codeforces 1323 D. Present(二进制+二分)_java_03
要求计算 Codeforces 1323 D. Present(二进制+二分)_java_04

我们分析答案的每一位,如果答案的第 Codeforces 1323 D. Present(二进制+二分)_java_05 位是 Codeforces 1323 D. Present(二进制+二分)_java_06,这意味着有奇数个 Codeforces 1323 D. Present(二进制+二分)_java_07 满足 Codeforces 1323 D. Present(二进制+二分)_java_08 的第 Codeforces 1323 D. Present(二进制+二分)_java_05 位是 Codeforces 1323 D. Present(二进制+二分)_java_06

首先我们要砍掉高于 Codeforces 1323 D. Present(二进制+二分)_java_05 位的信息(这对答案不产生影响),即让 Codeforces 1323 D. Present(二进制+二分)_java_12,于是第 Codeforces 1323 D. Present(二进制+二分)_java_05 位是 Codeforces 1323 D. Present(二进制+二分)_java_06Codeforces 1323 D. Present(二进制+二分)_java_15 的值只能在区间 Codeforces 1323 D. Present(二进制+二分)_java_16
这时如果固定 Codeforces 1323 D. Present(二进制+二分)_java_17 的值,Codeforces 1323 D. Present(二进制+二分)_java_18 的值的区间就是 Codeforces 1323 D. Present(二进制+二分)_java_19,因此能在排序后用二分快速计算满足 Codeforces 1323 D. Present(二进制+二分)_java_15 的第 Codeforces 1323 D. Present(二进制+二分)_java_05 位是 Codeforces 1323 D. Present(二进制+二分)_java_06Codeforces 1323 D. Present(二进制+二分)_java_23

AC代码:

int n, m, k;
int res, cnt, ans;
const int N = 4e5 + 10;
int a[N];
int b[N];
int main()
{
sd(n);
rep(i, 1, n)
sd(a[i]);
ans = 0;
rep(i, 0, 26)
{ //a[i]一定小于1<<26
int mod = 1 << (i + 1);
rep(j, 1, n)
b[j] = a[j] % mod;
int s = 0;
sort(b + 1, b + n + 1);
rep(j, 1, n)
{
int l, r;
l = lower_bound(b + 1, b + n + 1, (1 << i) - b[j]) - b;
r = lower_bound(b + 1, b + n + 1, (1 << (i + 1)) - b[j]) - b - 1;
s += (r - l + 1); //统计2^i到2^(i+1)-1区间内的解
l = lower_bound(b + 1, b + n + 1, (1 << i) + (1 << (i + 1)) - b[j]) - b;
r = lower_bound(b + 1, b + n + 1, (1 << (i + 2)) - b[j]) - b - 1;
s += (r - l + 1); //统计2^(i+1)+2^i到2^(i+2)-1区间内的解
if ((b[j] + b[j]) & (1 << i))
s--; //自己和自己相加的不算
}
if ((s / 2) & 1)
ans += 1 << i; //小于j和大于j的都记录了所以个数要除以2
}
pd(ans);
return 0;
}