整除分块 学习笔记

板子题

板子题-UVA11526
题目大意:
给定一个 n,求 i1nni。其中 n32 位无符号整数。

题目解析

显然如果暴力求解肯定是不可行的,显然会 TLE,所以我们需要找一种复杂度更优的算法。
我们可以先令 n=10,观察一下函数 f(x)=nx 的图像:

观察可以发现,不难发现:
x=1 的时候,f(x)=10
x=2 的时候,f(x)=5
x=3 的时候,f(x)=3
x=4,5 的时候,f(x)=2
x=6,7,8,9,10 的时候,f(x)=1
我们是否能够预处理出每个使 f(x) 相同的区间来更快地计算答案呢?
不难发现以下结论:

nN+,|{niiN+,in}|2n

证明:
in 时,ni 最多 n 个数字。
n<in 时,1nin,最多有 n 个数字。
因此最多只有 2n 个数字。

整除分块结论

对于一个数字 n,如果 ni=nj 成立,那么满足 i<jn 最大的 jnni
根据前面的结论,这种做法的复杂度为 Θ(n)
代码:

#include<cstdio>
#define ll long long
using namespace std;
ll n,ans;
void work(){
scanf("%lld",&n); ans=0; ll l=1,r;
while(l<=n){ r=n/(n/l); ans+=(r-l+1)*(n/l); l=r+1; }
printf("%lld",ans),putchar('\n'); return;
}
int main(){
int T; scanf("%d",&T); while(T--) work(); return 0;
}

引申

显然在一般的求值题目中的式子不会这么简单,一般都形如

i=1nf(i)ni

此时预处理出 f(x) 的前缀和 g(x) 就可以在 Θ(n) 求出这个式子的值了。
代码大致如下:

l=1,sum=0;
while(l<=n){
r=n/(n/l);
ans+=(g(r)-g(l-1))*(n/l);
l=r+1;
}

多维数论分块

如果求值的函数中含有 a1i+a2i++ani
那么我们只需要将前面的结论的 nni 改为 minj=1najaji 即可。
(当然 n=2,n=3 的情况比较常见)

posted @   jiangtaizhe001  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2021-04-25 洛谷 P5431 【模板】乘法逆元2 题解
点击右上角即可分享
微信分享提示