数论分块(整除分块)
数论分块(整除分块)
引入
给定 \(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);
}

浙公网安备 33010602011771号