CF1322B - Present
题意
N N N个数 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an,现在求 ( a 1 + a 2 ) ⊕ ( a 1 + a 3 ) ⊕ ⋅ ⋅ ⋅ ⊕ ( a n − 1 + a n ) (a_1+a_2)⊕(a_1+a_3)⊕···⊕(a_{n-1}+a_n) (a1+a2)⊕(a1+a3)⊕⋅⋅⋅⊕(an−1+an), N ≤ 400000 N\leq400000 N≤400000
题解
直接算是不行的
这里考虑计算二进制下
a
n
s
ans
ans的每一位
对于
a
n
s
ans
ans的第
k
k
k位答案,我们只需要考虑数
a
i
a_i
ai的
[
0
,
k
]
[0,k]
[0,k]位,因为超过
k
k
k位对第
k
k
k位没有影响
所以我们记
b
i
=
a
i
%
2
k
+
1
b_i=a_i\%2^{k+1}
bi=ai%2k+1,这样就保留了
[
0
,
k
]
[0,k]
[0,k]位的影响
然后我们要第
k
k
k位结果是
1
1
1的
b
i
+
b
j
b_i+b_j
bi+bj
而第
k
k
k位为1的数的范围为
[
2
k
,
2
k
+
1
−
1
]
[2^k,2^{k+1}-1]
[2k,2k+1−1]和
[
2
k
+
1
+
2
k
,
2
k
+
2
−
2
]
[2^{k+1}+2^k, 2^{k+2}-2]
[2k+1+2k,2k+2−2]
后面
2
k
+
2
−
2
2^{k+2}-2
2k+2−2这么来的:
b
[
i
]
∈
[
0
,
2
k
+
1
−
1
]
b[i]∈[0,2^{k+1}-1]
b[i]∈[0,2k+1−1],这里两个数,所以就是
2
k
+
2
−
2
2^{k+2}-2
2k+2−2
可以通过枚举
b
i
b_i
bi求得对应的
b
j
b_j
bj数量即可
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 4e5 + 10;
int N;
int a[MAX], b[MAX];
int pos(int x) { return lower_bound(b + 1, b + 1 + N, x) - b; }
int main() {
scanf("%d", &N);
for (int i = 1; i <= N; i++) scanf("%d", &a[i]);
int ans = 0;
for (int bit = 0; bit <= 25; bit++) {
int num = 1 << bit;
for (int i = 1; i <= N; i++) b[i] = (a[i] & (2 * num - 1));//和a[i] % (2 * num - 1)一样的
sort(b + 1, b + 1 + N);//排序
int cnt = 0;
for (int i = 1; i <= N; i++) {
cnt += pos(4 * num - b[i] - 1) - pos(3 * num - b[i]);//[3 * num, 4 * num - 2]间的数
cnt += pos(2 * num - b[i]) - pos(num - b[i]);//[num, 2 * num - 1]间的数
if ((2 * b[i]) & num) cnt--;//如果b[i]+b[i]的第k位是1, 就减去这种
}
if ((cnt / 2) & 1) ans ^= 1 << bit;//这里cnt/2是因为我们会算b[i]+b[j]和b[j]+b[i]两种
}
printf("%d\n", ans);
return 0;
}