整除分块学习笔记
整除分块学习笔记
值域分段求和
假如我们要对这样的式子进行求和:
\[\sum\limits_{i=1}^{n} f(i) \]
如果 \(f(i)\) 的取值有限,只有 \(m\) 个,且对于所有的 \(f(i)=x\) 在序列中都是连续的一段,那么就可以进行值域分段求和。
找出每个取值 \(x\) 在原序列中的第一次出现的位置 \(L_x\) 和最后一次出现的位置 \(R_x\),可以在 \(O(m)\) 的时间内算出答案(设 \(v_1,v_2\dots v_m\) 为 \(f(i)\) 的 \(m\) 种取值):
\[Ans=\sum\limits_{i=1}^{m}(R_i-L_i+1)v_i \]
例如:
\[\sum\limits_{i=1}^{n}\lfloor{log_2i}\rfloor \]
设 \(f(i)=\lfloor{log_2i}\rfloor\),容易发现 \(0\le f(i) \le log_2n\) 且单调递增。运用上述方法,可计算出 \(L_x=2^x,R_x=2^{x+1}-1\),于是可以在 \(O(logn)\) 的时间内求解:
\[Ans=\sum\limits_{i=1}^{\lfloor{log_2(n)}\rfloor}2^ii \]
整除分块
整除分块就是 依据整除的性质,对取值种类只有 \(\sqrt n\) 级别的 \(f\) 序列进行的值域分段求和。
举几个简单的例子:
\[\sum\limits_{i=1}^{n}\lfloor{\frac{n}{i}}\rfloor \]
设 \(f(i)=\lfloor{\frac{n}{i}}\rfloor\),则 \(f(i)\) 的取值不超过 \(2\sqrt n\) 种且单调递增。运用上述方法,可计算出 \(L_x=\lfloor\frac{n}{\lfloor\frac{n}{x-1}\rfloor}\rfloor+1,R_x=\lfloor\frac{n}{\lfloor\frac{n}{x}\rfloor}\rfloor\),值域分段求和即可,时间复杂度 \(O(\sqrt{n})\)。
代码片段:
for(int l=1,r=0;
l<=n;
) {
l=r+1,r=n/(n/l);
ans+=(n/l)*(r-l+1);
}
\[\sum\limits_{i=1}^{n}i^2\lfloor{\frac{n}{i}}\rfloor \]
设 \(f(i)=\lfloor{\frac{n}{i}}\rfloor\),仍然有 \(L_x=\lfloor\frac{n}{\lfloor\frac{n}{x-1}\rfloor}\rfloor+1,R_x=\lfloor\frac{n}{\lfloor\frac{n}{x}\rfloor}\rfloor\)。考虑对于每一段 \([L_x,R_x]\) 计算答案的贡献:
\(\sum\limits_{i=L_x}^{R_x}i^2x\)
\(=x\sum\limits_{i=L_x}^{R_x}i^2\)
\(=x(\sum\limits_{i=1}^{R_x}i^2-\sum\limits_{i=1}^{L_x-1}i^2)\)
\(=x(\frac{R_x(R_x+1)(2R_x+1)}{6}-\frac{L_x(L_x+1)(2L_x+1)}{6})\)
然后就可以 \(O(\sqrt 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);
}
习题:
- [CQOI2007]余数求和
- [清华集训2012]模积和
推荐阅读
- JavaWeb学习记录——servlet+tomcat+request+respond+JSP实战项目(使用MVC模式开发)
- 算法|复现经典(《统计学习方法》第21章 PageRank算法)
- 神经网络|(翻译)60分钟入门深度学习工具-PyTorch
- 渗透测试-01(渗透入门)
- (数据科学学习手札135)tenacity(Python中最强大的错误重试库)
- TCP客户端和服务端的互通信息
- Python全栈之学习MySQL(1)
- DevOps Master凤凰沙盘的学习体验
- 【职业技能提升】职业技能培训在线学习系统2022版.net源码
- 详解JUC并发编程中的进程与线程学习