整除分块学习笔记

值域分段求和

假如我们要对这样的式子进行求和:

i=1nf(i)

如果 f(i) 的取值有限,只有 m 个,且对于所有的 f(i)=x 在序列中都是连续的一段,那么就可以进行值域分段求和

找出每个取值 x 在原序列中的第一次出现的位置 Lx 和最后一次出现的位置 Rx,可以在 O(m) 的时间内算出答案(设 v1,v2vmf(i)m 种取值):

Ans=i=1m(RiLi+1)vi


例如:

i=1nlog2i

f(i)=log2i,容易发现 0f(i)log2n 且单调递增。运用上述方法,可计算出 Lx=2x,Rx=2x+11,于是可以在 O(logn) 的时间内求解:

Ans=i=1log2(n)2ii


整除分块

整除分块就是 依据整除的性质,对取值种类只有 n 级别的 f 序列进行的值域分段求和

举几个简单的例子:


i=1nni

f(i)=ni,则 f(i) 的取值不超过 2n 种且单调递增。运用上述方法,可计算出 Lx=nnx1+1,Rx=nnx,值域分段求和即可,时间复杂度 O(n)

代码片段:

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

i=1ni2ni

f(i)=ni,仍然有 Lx=nnx1+1,Rx=nnx。考虑对于每一段 [Lx,Rx] 计算答案的贡献:

i=LxRxi2x

=xi=LxRxi2

=x(i=1Rxi2i=1Lx1i2)

=x(Rx(Rx+1)(2Rx+1)6Lx(Lx+1)(2Lx+1)6)

然后就可以 O(n) 求解了。

代码片段:

for(int l=1,r=0; l<=n;) {
        l=r+1,r=n/(n/l);
        ans+=(n/l)*((r*(r+1)*(r<<1|1)/6-l*(l+1)*(l<<1|1)/6);
}

习题:

posted @   栾竹清影  阅读(87)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示