数论分块(整除分块)

数论分块(整除分块)

引入

给定 \(n\)\(n\le 10^9\)) 求解:\(\sum\limits_{i=1}^{n}\lfloor\cfrac{n}{i}\rfloor\)

暴力算法:\(O(n)\) 无法通过。

假设 \(n=10\),则可以发现:

  • \(i=1\) 时,\(\lfloor\cfrac{10}{i}\rfloor=10\)
  • \(i=2\) 时,\(\lfloor\cfrac{10}{i}\rfloor=5\)
  • \(i=3\) 时,\(\lfloor\cfrac{10}{i}\rfloor=3\)
  • \(i=4,5\) 时,\(\lfloor\cfrac{10}{i}\rfloor=2\)
  • \(i=6,7,8,9,10\) 时,\(\lfloor\cfrac{10}{i}\rfloor=1\)

注意到实际上取值非常有限,甚至出现连续 \(5\) 个取值相同,考虑能不能根据相同的 \(\lfloor\cfrac{n}{i}\rfloor\) 分块,最终答案为:

\[\sum_{i=1}^{\text{块数}}\text{(块的值)}\times\text{(块的答案)} \]

时间复杂度

现在对块数(时间复杂度),进行证明:

  • \(i\le \sqrt n\) 时,\(i\)\([1,\sqrt n]\) ,共 \(\sqrt n\) 种取值。
  • \(i>\sqrt n\) ,即 \(\lfloor\cfrac{n}{i}\rfloor<\sqrt n\) 时,\(\lfloor\cfrac{n}{i}\rfloor\)\([1,\sqrt n-1]\) ,共 \((\sqrt n-1)\) 种取值。

故共 \((2\sqrt n-1)\) 种取值,时间复杂度 \(O(\sqrt n)\)

算法

问题现在集中于如何确定块的边界,也就是已知左端点 \(l\),如何快速求解右端点 \(r\)

分析本质,令块的值 \(k=\lfloor\cfrac{n}{l}\rfloor\),问题就是找到一个最大的 \(r\) ,使得 \(\lfloor\cfrac{n}{r}\rfloor=k\)

即:

\[k\le\cfrac{n}{r} \]

移相:

\[r\le\cfrac{n}{k} \]

由于 \(r\) 为正整数,所以:

\[r_{max=}\lfloor\cfrac{n}{k}\rfloor \]

\(k\) 代换,即可得到 \(r\) 的取值:

\[r_{max=}\lfloor\cfrac{n}{\lfloor\cfrac{n}{l}\rfloor}\rfloor \]

代码:

int sum = 0,r = 0; // 这里为求和
for (int l = 1;l <= n;l = r + 1) {
  r = (n / (n / l));
  sum += (r - l + 1) * (n / l);
}
posted @ 2026-07-19 18:12  SilverWolf_lhh  阅读(6)  评论(0)    收藏  举报