整除分块简述

整除分块其实是一种比较简单的 \(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]余数求和 了。

posted @ 2025-02-07 20:56  袍蚤  阅读(59)  评论(1)    收藏  举报