例题:
求 ∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^n \lfloor \frac n i \rfloor ∑i=1n⌊in⌋
O ( n ) O(n) O(n) 的做法很显然,但是一般n会很大,于是有了除法分块。
对于一段连续的 i i i, ⌊ n i ⌋ \lfloor \dfrac n i \rfloor ⌊in⌋ 可能是相同的,比如说当 i i i 的值在区间 [ 6 , 10 ] [6,10] [6,10] 时, ⌊ n i ⌋ = 1 \lfloor \dfrac n i \rfloor=1 ⌊in⌋=1,都是相同的,于是问题转变成了要找到这些区间。
于是有了这样的递归过程(证明在下面):
int l=1,r;
while(l<=n)
{
r=n/(n/l);
当前的区间就是l~r,这个区间的值为n/l
l=r+1;
}
看起来是很简单,证明事实上也很简单。
l l l 的初值为 1 1 1 是毫无疑问的,递归时 l = r + 1 l=r+1 l=r+1 也是毫无疑问的,重点时 r r r 的值是如何确定的。
证明1(反证法):
显然 r r r 满足 ⌊ n r ⌋ = ⌊ n l ⌋ \lfloor \dfrac n r \rfloor=\lfloor \dfrac n l \rfloor ⌊rn⌋=⌊ln⌋,需要证明的是 r r r 是这个区间的边界。
设 r r r 不是这个区间的边界,那么至少有 r + 1 r+1 r+1 满足 ⌊ n r + 1 ⌋ = ⌊ n l ⌋ \lfloor \dfrac n {r+1} \rfloor=\lfloor \dfrac n l \rfloor ⌊r+1n⌋=⌊ln⌋。
设 ⌊ n r ⌋ = ⌊ n l ⌋ = x \lfloor \dfrac n r \rfloor=\lfloor \dfrac n l \rfloor=x ⌊rn⌋=⌊ln⌋=x。
因为 ⌊ n r + 1 ⌋ \lfloor \dfrac n {r+1} \rfloor ⌊r+1n⌋ 是向下取整,所以有
⌊
n
r
+
1
⌋
×
(
r
+
1
)
≤
n
\lfloor \dfrac n {r+1}\rfloor\times (r+1) \leq n
⌊r+1n⌋×(r+1)≤n
x
×
(
r
+
1
)
≤
n
x \times (r+1) \leq n
x×(r+1)≤n
x
×
(
r
+
1
)
x
≤
⌊
n
x
⌋
\dfrac {x \times (r+1)} x\leq \lfloor\dfrac n x \rfloor
xx×(r+1)≤⌊xn⌋
因为 r = ⌊ n x ⌋ r=\lfloor \dfrac n x \rfloor r=⌊xn⌋,那么有
x × ( r + 1 ) x ≤ r \dfrac {x \times (r+1)} x\leq r xx×(r+1)≤r
r + 1 ≤ r r+1\leq r r+1≤r
柿子不成立,则得证。
证明2:
依然设 ⌊ n l ⌋ = x \lfloor \dfrac n l \rfloor=x ⌊ln⌋=x。
现在要找到一个最大的 r r r,满足 x × r ≤ n x \times r \leq n x×r≤n。
移项得 r ≤ ⌊ n x ⌋ r \leq \lfloor \dfrac n x \rfloor r≤⌊xn⌋
所以 r r r 的最大值为 ⌊ n x ⌋ \lfloor \dfrac n x \rfloor ⌊xn⌋。
时间复杂度为 O ( 2 n ) O(2\sqrt n) O(2n),这个也很好证明,当 x ≤ n x\leq \sqrt n x≤n 时, x x x 只有 n \sqrt n n 种取值,也就是说这样的块数不会超过 n \sqrt n n 块;当 x ≥ n x \geq \sqrt n x≥n 时,有 ⌊ n x ⌋ ≤ n \lfloor \dfrac n x \rfloor \leq \sqrt n ⌊xn⌋≤n,也就是说此时 l l l 和 r r r 的取值都 ≤ n \leq \sqrt n ≤n,所以这样的块数也不会超过 n \sqrt n n 块。
如果将问题的形式转变一下,比如说:
∑
i
=
1
n
(
⌊
n
i
⌋
)
k
\sum_{i=1}^n (\lfloor \frac n i \rfloor)^k
i=1∑n(⌊in⌋)k
又比如说
∑
i
=
1
n
⌊
n
i
⌋
⌊
m
i
⌋
\sum_{i=1}^n \lfloor \frac n i \rfloor \lfloor \frac m i \rfloor
i=1∑n⌊in⌋⌊im⌋
更比如说
∑
i
=
1
n
(
⌊
n
i
⌋
−
⌊
m
i
⌋
)
k
\sum_{i=1}^n (\lfloor \frac n i \rfloor-\lfloor \frac m i \rfloor)^k
i=1∑n(⌊in⌋−⌊im⌋)k
不管如何变,这些其实都是可以用除法分块来做的,不要被形式迷惑了。