一、前言
在计算 ∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^{n}⌊\frac{n}{i}⌋ ∑i=1n⌊in⌋的时候,枚举的时间复杂度是O(n),当n很大的时候我们是无法接受的,由于 [ n i ] [\frac{n}{i}] [in]中有很多重复的区间,所以我们需要一种更高效的算法。
二、引理
⌊ ⌋为向下取整符号
引理1:任意整数a,b,c有
⌊
a
b
c
⌋
=
⌊
⌊
a
b
⌋
c
⌋
⌊\frac{a}{bc}⌋=⌊\frac{⌊\frac{a}{b}⌋}{c}⌋
⌊bca⌋=⌊c⌊ba⌋⌋
证明:
a
b
=
⌊
a
b
⌋
+
r
\frac{a}{b}= ⌊\frac{a}{b}⌋ +r
ba=⌊ba⌋+r(0<=r<1)
⌊
a
b
c
⌋
=
⌊
a
b
∗
1
c
⌋
=
⌊
a
b
∗
1
c
⌋
=
⌊
1
c
∗
(
⌊
a
b
⌋
+
r
)
⌋
=
⌊
⌊
a
b
⌋
c
⌋
⌊\frac{a}{bc} ⌋ = ⌊\frac{a}{b}*\frac{1}{c}⌋ = ⌊\frac{a}{b}*\frac{1}{c}⌋ = ⌊\frac{1}{c}*(⌊\frac{a}{b}⌋+r)⌋=⌊\frac{⌊\frac{a}{b}⌋}{c}⌋
⌊bca⌋=⌊ba∗c1⌋=⌊ba∗c1⌋=⌊c1∗(⌊ba⌋+r)⌋=⌊c⌊ba⌋⌋
引理2:

三、证明
如果我们从左找到了一个任意的 i,那么只需找到最大的 j(i<=j<=n),满足
⌊
n
i
⌋
=
⌊
n
j
⌋
⌊\frac{n}{i}⌋=⌊\frac{n}{j}⌋
⌊in⌋=⌊jn⌋,则 i - j 的区间就是我们要求的长度。
j =
⌊
n
⌊
n
j
⌋
⌋
=
⌊
n
⌊
n
i
⌋
⌋
⌊\frac{n}{⌊\frac{n}{j}⌋}⌋=⌊\frac{n}{⌊\frac{n}{i}⌋}⌋
⌊⌊jn⌋n⌋=⌊⌊in⌋n⌋

四、模板代码
for(ll l=1,r; l<=n; l=r+1)
{
r = n/(n/l);
ans += (r-l+1)*(n/l);
}
时间复杂度为 O ( n ) O(\sqrt{n}) O(n)
381

被折叠的 条评论
为什么被折叠?



