异 或 约 数 和 异或约数和 异或约数和
最 初 想 法 \color{blue}{最初想法} 最初想法
[
1
,
x
]
[1, x]
[1,x] 内含有
x
x
x 这个约数的数个数为
c
n
t
=
⌊
N
x
⌋
cnt = \lfloor \frac{ N } { x } \rfloor
cnt=⌊xN⌋,
当
c
n
t
cnt
cnt 为偶数时, 贡献为
0
0
0, 当
c
n
t
cnt
cnt 为奇数时, 对整体答案贡献为 异或
x
x
x,
枚举
x
∈
[
1
,
N
]
x∈[1,N]
x∈[1,N] 直接计算贡献, 复杂度
O
(
N
)
O(N)
O(N) .
用 整除分块 加上类似 这里 的方法可以优化到
O
(
N
l
o
g
N
)
O(\sqrt{N}logN)
O(NlogN), 但是仍然不能
A
C
AC
AC.
正 解 部 分 \color{red}{正解部分} 正解部分
有一个规律, 设 g ( x ) g(x) g(x) 为 [ 1 , x ] [1,x] [1,x] 内的异或和, 则
g ( x ) = { 0 奇 数 x e l s e + { 1 ⌈ N 2 ⌉ 为 奇 数 0 e l s e g(x)= \begin{cases} 0\ \ \ \ 奇数\\ x\ \ \ else \end{cases} +\begin{cases} 1 \ \ \ \ \lceil \frac{N}{2}\rceil为奇数 \\ 0 \ \ \ \ else\end{cases} g(x)={0 奇数x else+{1 ⌈2N⌉为奇数0 else
于是前面需要 O ( l o g N ) O(logN) O(logN) 计算的只需要 O ( 1 ) O(1) O(1) 了, 总体复杂度 O ( N ) O(\sqrt{N}) O(N) , 可以 A C AC AC .
实 现 部 分 \color{red}{实现部分} 实现部分
没什么好说的 …
#include<bits/stdc++.h>
#define reg register
typedef long long ll;
ll N;
ll Ans;
ll Sum(ll x){
if(!x) return 0;
ll s_1, s_2;
if(x & 1) s_1 = 0;
else s_1 = x;
ll tmp = (N-1)/x + 1;
if(tmp & 1) s_2 = 1;
else s_2 = 0;
return s_1 + s_2;
}
int main(){
scanf("%lld", &N);
for(reg ll l = 1, r; l <= N; l = r+1){
r = N/(N/l);
if((N/l & 1) == 0) continue ;
Ans ^= Sum(r) ^ Sum(l-1);
}
printf("%lld\n", Ans);
return 0;
}