洛谷【数学 1】基础数学问题:最小公倍数的计算与应用
1. 引言
在数论领域中,约数是基础而重要的概念。无论是判断质数、分解质因数,还是计算最大公约数或研究数论函数,都离不开约数的身影。计算"1到n中所有数的约数个数总和"这一经典问题,不仅能深化我们对约数本质的理解,更能展现数学思维在算法优化中的精妙应用。
洛谷 P1403 正是这样一道典型题目:给定正整数n,计算1到n中所有整数的约数个数之和。这道看似简单的题目,从暴力求解到高效优化的完整思维过程,堪称基础数学问题的完美范例。本文将系统解析其代码实现、数学原理、优化方法及实际应用。
2. 代码解析
题目参考代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){int n,ans=0;cin>>n;for(int i=1;i<=n;i++) ans+=(n/i);cout<<ans;return 0;
}
这段代码简洁到让人惊讶 —— 仅有几行却能解决问题。我们逐行解析其逻辑:
-
首先通过
#include<bits/stdc++.h>
引入标准库,using namespace std;
简化命名空间使用,这是 C++ 编程中的常见开头。 -
在
main
函数中,定义整数n
(输入的正整数)和ans
(存储答案的变量,初始化为 0)。 -
通过
cin>>n
读取输入的 n。 -
核心逻辑是循环:
for(int i=1;i<=n;i++) ans+=(n/i);
,即从 1 到 n 遍历每个 i,将n/i
累加到ans
中。 -
最后输出
ans
并结束程序。
初看之下,这个循环的逻辑可能不够直观:为什么累加 n/i
就能得到约数个数总和?这正是我们需要通过数学原理来解释的核心问题。
3. 数学原理
问题本质:计算1到n所有数的约数个数之和。
常规思路的局限
传统方法是逐个计算每个数 k 的约数个数后求和。例如:
-
1的约数:1(1个)
-
2的约数:1,2(2个)
-
...
-
5的约数:1,5(2个)
当n=5时,总和为1+2+2+3+2=10
该方法时间复杂度为 O(n√n) ,当 n 较大时(如1e6)效率不足。
统计视角转换
代码的核心思想是:统计每个数i作为约数出现的总次数,而非逐个计算约数个数。
对于任意整数 i ,在1到n范围内作为约数的次数为 ⌊n/i⌋ 。例如 n=5 时:
-
i=1:出现5次(1,2,3,4,5)
-
i=2:出现2次(2,4)
-
...
-
i=5:出现1次(5)
累加结果5+2+1+1+1=10,验证了公式:总和=Σ⌊n/i⌋(i从1到n)
4. 代码优化
原始代码的时间复杂度是 O (n),当 n≤1e6 时可以正常运行,但当 n 达到 1e9 时,O (n) 的循环会超时(约需 1e9 次运算,远超程序运行时间限制)。此时需要用整除分块(数论分块)进行优化。
整除分块的原理
观察⌊n/i⌋
的值会发现:在很多连续的 i 上,⌊n/i⌋
的值是相同的。例如 n=10 时:
-
i=1→10/1=10;i=2→5;i=3→3;i=4→2;i=5→2;i=6→1;i=7→1;i=8→1;i=9→1;i=10→1。
其中 i=4 和 i=5 时,⌊10/i⌋=2
;i=6 到 i=10 时,⌊10/i⌋=1
。这些连续的 i 构成 “块”,每个块内的⌊n/i⌋
值相同,因此可以批量计算。
对于某个值 v=⌊n/i⌋,对应的最大 i 值为⌊n/v⌋
。因此,每个块的范围是[l, r]
,其中 l 是当前起始位置,r=⌊n/v⌋,该块的贡献为 v*(r-l+1)。
优化后的代码实现
#include<bits/stdc++.h>
using namespace std;
int main(){int n,ans=0;cin>>n;for(int l=1,r;l<=n;l=r+1){r=n/(n/l); // 计算当前块右边界ans+=(n/l)*(r-l+1); // 累加块贡献}cout<<ans;return 0;
}
优化后时间复杂度降至O(√n),因为⌊n/i⌋的不同取值不超过2√n个。
5. 实际应用
约数总和计算在以下领域有重要应用:
-
数论基础:计算约数和、欧拉函数等
-
密码学:RSA加密等算法的质数约数特性分析
-
算法竞赛:常见于"统计约数为偶数的数"等衍生问题
-
数据统计:数值因子分布分析
6. 扩展阅读
推荐学习资源:
-
《算法竞赛进阶指南》数论分块章节
-
洛谷数论专题练习
-
约数个数定理:n=p1^a1...pk^ak时,约数个数为(a1+1)...(ak+1)
-
相关题目:P2424(约数和)、P3935(数论综合)
7. 练习题目
巩固练习:
-
洛谷P1403(原题)
-
P2424约数和问题
-
P3935 Calculating(约数个数为奇数的数统计)
-
P1463反素数(约数个数最多的数)
8. 总结
本文通过P1403题解,揭示了:
-
视角转换的价值:从"计算约数"到"统计出现次数"
-
整除分块的优化思想:O(n)→O(√n)的效率提升
-
数论基础的重要性:为复杂问题提供解决思路
建议通过具体案例手动演算,深化对约数统计和分块优化的理解。
9. 附录
洛谷P1403原题链接:P1403 [AHOI2005] 约数研究