题意:
给一个长度为
n
n
n 的序列
a
a
a
要求计算
(
a
1
+
a
2
)
⊕
(
a
1
+
a
3
)
⊕
…
⊕
(
a
1
+
a
n
)
⊕
(
a
2
+
a
3
)
⊕
…
⊕
(
a
2
+
a
n
)
…
⊕
(
a
n
−
1
+
a
n
)
(a_1+a_2)⊕(a_1+a_3)⊕…⊕(a_1+a_n)⊕(a_2+a_3)⊕…⊕(a_2+a_n)…⊕(a_{n−1}+a_n)
(a1+a2)⊕(a1+a3)⊕…⊕(a1+an)⊕(a2+a3)⊕…⊕(a2+an)…⊕(an−1+an)
我们分析答案的每一位,如果答案的第 i i i 位是 1 1 1,这意味着有奇数个 ( j , k ) (j,k) (j,k) 满足 a j + a k aj+ak aj+ak 的第 i i i 位是 1 1 1
首先我们要砍掉高于
i
i
i 位的信息(这对答案不产生影响),即让
b
j
=
a
j
b_j=a_j%(1<<(i+1))
bj=aj,于是第
i
i
i 位是
1
1
1 的
b
j
+
b
k
b_j+b_k
bj+bk 的值只能在区间
[
2
i
,
2
i
+
1
−
1
]
∪
[
2
i
+
1
+
2
k
,
2
i
+
2
−
1
]
[2^i,2^{i+1}-1]∪[2^{i+1}+2^k,2^{i+2}−1]
[2i,2i+1−1]∪[2i+1+2k,2i+2−1] 中
这时如果固定
j
j
j 的值,
b
k
b_k
bk 的值的区间就是
[
2
i
−
b
j
,
2
i
+
1
−
1
−
b
j
]
∪
[
2
i
+
1
+
2
k
−
b
j
,
2
i
+
2
−
1
−
b
j
]
[2^i−b_j,2^{i+1}−1−b_j]∪[2^{i+1}+2^k−b_j,2^{i+2}−1−b_j]
[2i−bj,2i+1−1−bj]∪[2i+1+2k−bj,2i+2−1−bj],因此能在排序后用二分快速计算满足
b
j
+
b
k
b_j+b_k
bj+bk 的第
i
i
i 位是
1
1
1 的
k
k
k 的个数。
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;
}