整除分块简述
整除分块其实是一种比较简单的 \(trick\),主要是和莫比乌斯反演放在一起使用。
向下取整
例如,给你一个式子 $\sum_{i=1}^{n}\left \lfloor \frac{n}{i} \right \rfloor $ 求值,这个时候我们就可以使用整除分块。
显然我们可以发现,当 \(i\) 取不同的值时,$\left \lfloor \frac{n}{i} \right \rfloor $ 的值可能是相同的,并且这一段相同的一定是连续的。所以我们可以尝试把相同的段作为一个整体来处理。
现在我们遇到的问题:如何分段?如何处理段内的值?
我们设这一个段,它的左边界是 \(l\),右边界是 \(r\),段内每个值都是 \(k\)(则段长自然是 \((r-l+1)\),段内总值为 \((r-l+1)*k\))
所以我们可以得到 \(k=\left \lfloor \frac{n}{l} \right \rfloor\)。
由于每一段内的值都是相同的,所以一定有 \(i*k \le n\)。
由此函数非严格的单调性可以得到 \(i_{max}*k \le n\),然后 \(i_{max}\) 其实就是 \(r\)。
联立两个式子\(\left\{\begin{array}{l} k=\left\lfloor\frac{n}{l}\right\rfloor \\ \ rk \leq n \end{array}\right.\)
解得 $r=\left \lfloor \frac{n}{\left \lfloor \frac{n}{l} \right \rfloor } \right \rfloor $。
然后就可以写代码了。
for(int l=1,r;l<=n;r=l+1)
{
k=n/l;
r=n/k;
tot+=(r-l+1)*k;
}
时间复杂度是 \(O(\sqrt n)\)
向上取整
例如,给你一个式子 $\sum_{i=1}^{n} \left \lceil \frac{n}{i} \right \rceil $ 求值。
我们只需要把其转化为向下取整。
如何转化?观察发现,我们因为整除的存在,我们无法直接写成向下取整加1的形式。我们只需要对每个 $\frac{n}{i} $ 加上 $\frac{i-1}{i} $ 就可以把其转化为向下取整的形式了。
即:一定有: $\sum_{i=1}^{n} \left \lceil \frac{n}{i} \right \rceil = {\sum_{i=1}^{n}\left \lfloor \frac{n+i-1}{i} \right \rfloor } $
然后就可以整除分块了。
取模
因为$k \bmod i = n - \left \lfloor \frac{n}{i} \right \rfloor *i $
所以我们就可以解决形如 $ {\sum_{i=1}^{k}} k \bmod i$ 的式子求值问题了(每个段内都是等差数列求和)
多维整除分块
形如 $\sum_{i=1}^{n}\left \lfloor \frac{a1}{i} \right \rfloor * \left \lfloor \frac{a2}{i} \right \rfloor $ 的式子,也可以用整除分块,只是 右端点是每一个分段中最小右端点,即 : $ r = \min {\left \lfloor \frac{a_i}{\left \lfloor \frac{a_i}{i} \right \rfloor } \right \rfloor } $,计算其时间复杂度还是根号级别的。
然后你就可以去做 P2261 [CQOI2007]余数求和 了。

浙公网安备 33010602011771号