看了一下网上的解析,大多比较简略,使本蒟蒻感到为难,所以决定死磕到底并写一篇讲解。
一看这个 solve1 就不好对付,我们要先理论分析一下,再进行模拟。
第一个循环很像质数筛,发现
p
[
i
]
p[i]
p[i] 就是用来标记质数的,目前还是质数值就为 1。发现
d
=
i
1
,
i
2
,
i
3
,
…
,
i
k
(
i
k
≤
n
)
d={i^1,i^2,i^3,\dots,i^k(i^k\le n)}
d=i1,i2,i3,…,ik(ik≤n),反转之后是
i
k
,
i
k
−
1
,
…
,
i
2
,
i
1
i^k,i^k-1,\dots,i^2,i^1
ik,ik−1,…,i2,i1。接下来遍历了每一个
d
d
d 中的元素
k
k
k,这里的
j
j
j 则遍历了
k
k
k 的倍数,并且把
p
j
p_j
pj 标记为 0,表示找到了因数,
j
j
j 不是质数。这里的
i
i
i 是质数,所以
f
j
f_j
fj 应该是记录了把
p
j
p_j
pj 标记为 0 的时的质数。
g
j
=
k
g_j=k
gj=k,记录了
j
j
j 的质因数分解中有
x
x
x 个
i
i
i,
g
j
=
i
x
g_j=i^x
gj=ix。现在明白了,反转是为了让
g
j
g_j
gj 记录到最大的
x
x
x,把
p
j
p_j
pj 标记为 0 之后就不会再更改
f
f
f 和
g
g
g 的值了,遂取到最大值。发现了
f
j
f_j
fj 只会记录第一次枚举到的
i
i
i,我们再完善一下
f
j
f_j
fj 的定义:
f
j
f_j
fj 是
j
j
j 最小的质因子。
第二个循环,如果这个数有至少两个质因子(即是合数),必然有一个质因子
i
<
=
⌊
n
⌋
i<=\lfloor\sqrt{n}\rfloor
i<=⌊n⌋,在第一个循环中被筛掉。此时所有合数已经被筛掉了,可以把
⌊
n
⌋
\lfloor\sqrt{n}\rfloor
⌊n⌋ 以上的质数
i
i
i 的
f
i
,
g
i
f_i,g_i
fi,gi 都标成
i
i
i,符合之前的定义。
第三个循环我是真的看不懂,于是先把之前的结论记下来,暴力模拟。本人做题时的草稿纸:
发现
f
i
f_i
fi 正是
i
i
i 的所有因数之和!!!所以 solve1 返回的是
n
n
n 以内所有正整数因数之和的总和。具体原因其实不一定要听懂(我绝对不会告诉你我没看懂解析)。
solve1 做完整个人精神饱满,开始对 solve2 进行模拟,发现
n
=
10
n=10
n=10 时答案竟然相同!思考了亿会儿,发现n/i
表示
n
n
n 以内有因数
i
i
i 的数(
i
i
i 的倍数)有几个,再乘上
i
i
i,就统计了所有
n
n
n 以内的数中因数
i
i
i 的总和,最后返回的也是所有数因数之和的总和,只是从两种角度统计,从 1 到
n
n
n 的每个数和从具体的因数是几。于是乎轻松搞定(嚎叫)。
CSP-S 2023 初赛 阅读程序 第二题 程序功能详解
于 2024-09-20 16:57:46 首次发布