「数论」整除分块

题目

  • 给定正整数 $n$,求如下式子的值:

$$sum_{i=1}^n lfloor frac{n}{i} floor$$

  • 答案对一个数取模,$n le 10^{15}$,时间限制 2s。

思考

  如果我们暴力求解,复杂度是 $O(n)$ 的,那程序几天也跑不完。

  思考一下,其实我们的瓶颈,就是出于 $i$ 太多了。

  那枚举什么量,才能让枚举的数量变少?

  请看下面这张图,这是一个反比例函数图象的其中一支(图片绘于 desmos):

  我们把 $f(x)=frac{10^{15}}{x}$,$y=lfloor f(x) floor$ 的图象画了出来。

  明显地看到,在 $x$ 比较大的时候,$frac{10^{15}}{x}$ 十分靠近 $x$ 轴。

  这么说明,随着 $x$ 越来越大,相同的 $y$ 的值也会越来越多。

  像 $n=10^{15}$ 的时候,$frac{10^{15}}{5 imes 10^{14}+1}$ 到 $frac{10^{15}}{10^{15}}$ 下取整的值都是 1。

  按照刚刚的枚举方法,相当于你有约一半的枚举量都浪费于答案为 1 的情况了。

  那……我们枚举答案

  好办法!

整除分块

  一个数字,最多有多少个因数?

  最理想的状态下,这个数满足:$forall i in [1,sqrt{n}], i mid n$。

  为什么这个数是最理想的,因为如果 $i$ 大于 $sqrt{n}$,且 $i mid n$,则 $frac{n}{i}$ 肯定在 $[1, sqrt{n}]$ 范围内,必出现过。

  所以这个数就是因数尽可能多的数。

  同时有一个结论,若 $i mid n$,则 $frac{n}{i} mid n$。

  所以,$n$ 的因数个数最多不超过 $2 imes sqrt{n}$,取整后的不同答案也不会超过 $2 imes sqrt{n}$。

  因此,不同答案的个数不超过 $2 imes sqrt{n}$。

  而观察数据范围,$2 imes sqrt{n}$ 在可以接受的范围内。

  如果能够设计出一种刚好能枚举所有因数的算法,这道题就可以被解决。

  现在来推导一下:

  • 不论 $n$ 取多大,$n$ 一定为它自己的因数,以下以 $n=10$ 为例。
  • 因此,当 $iin [1,1]$ 时,$frac{10}{i}$ 答案为 $10$。
  • 接下来让枚举区间左端点设为原右端点 + 1,即 $[2,1]$。
  • 容易得到,这时区间内每个数的答案均为 $lfloorfrac{10}{2} floor=5$,即为 $a$。
  • 可以得出右端点 $r=lfloorfrac{10}{5} floor=2$。
  • 此时答案区间为 $[2,2]$,累计为 $a imes (r-l+1)=5$。
  • 当区间 $[3,3]$ 计算完毕时,左端点变为 $2+1=3$。
  • 此时区间内每个数答案均为 $lfloorfrac{10}{3} floor=3$。
  • 可以得出右端点 $r=lfloorfrac{10}{3} floor=3$。
  • 此时答案区间为 $[3,3]$,累计为 $3 imes (3-3+1)=3$。
  • 当区间 $[3,3]$ 计算完毕时,左端点变为 $3+1=4$。
  • 此时区间内每个数答案均为 $lfloorfrac{10}{4} floor=2$。
  • 可以得出右端点 $r=lfloorfrac{10}{2} floor=5$。
  • 此时答案区间为 $[4,5]$,累计为 $2 imes (5-4+1)=4$。
  • 最后,左端点变为 $5+1=6$。
  • 此时区间内每个数答案均为 $lfloorfrac{10}{6} floor=1$。
  • 可以得出右端点 $r=lfloorfrac{10}{1} floor=10$。
  • 此时答案区间为 $[6,10]$,累计为 $1 imes (10-6+1)=5$。
  • 发现右端点已经到 $n$ 了,停止算法。
  • 答案为 $10+5+3+4+5=27$,与 $10+5+3+2+2+1+1+1+1+1=27$ 一致。

  很明显,这个算法将 $frac{n}{i}$ 相同的情况整合到一块共同处理,效率提高不少。

原文地址:https://www.cnblogs.com/zengpeichen/p/13787430.html