整除分块简述

整除分块其实是一种比较简单的 trick,主要是和莫比乌斯反演放在一起使用。

向下取整

例如,给你一个式子 i=1nni 求值,这个时候我们就可以使用整除分块。

显然我们可以发现,当 i 取不同的值时,ni 的值可能是相同的,并且这一段相同的一定是连续的。所以我们可以尝试把相同的段作为一个整体来处理。

现在我们遇到的问题:如何分段?如何处理段内的值?

我们设这一个段,它的左边界是 l,右边界是 r,段内每个值都是 k(则段长自然是 (rl+1),段内总值为 (rl+1)k

所以我们可以得到 k=nl

由于每一段内的值都是相同的,所以一定有 ikn

由此函数非严格的单调性可以得到 imaxkn,然后 imax 其实就是 r

联立两个式子{k=nl rkn

解得 r=nnl

然后就可以写代码了。

for(int l=1,r;l<=n;r=l+1)
{
	k=n/l;
	r=n/k;
	tot+=(r-l+1)*k;
}

时间复杂度是 O(n)

向上取整

例如,给你一个式子 i=1nni 求值。

我们只需要把其转化为向下取整。

如何转化?观察发现,我们因为整除的存在,我们无法直接写成向下取整加1的形式。我们只需要对每个 ni 加上 i1i 就可以把其转化为向下取整的形式了。

即:一定有: i=1nni=i=1nn+i1i

然后就可以整除分块了。

取模

因为kmodi=nnii
所以我们就可以解决形如 i=1kkmodi 的式子求值问题了(每个段内都是等差数列求和)

多维整除分块

形如 i=1na1ia2i 的式子,也可以用整除分块,只是 右端点是每一个分段中最小右端点,即 : r=minaiaii,计算其时间复杂度还是根号级别的。

然后你就可以去做 P2261 [CQOI2007]余数求和 了。

posted @   袍蚤  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示