一、学习目标
- 理解"最长连续因子"问题的核心解法,掌握因子判断 、连续序列遍历的逻辑;
- 学会优化循环遍历范围(利用平方根减少计算量);
- 识别并修正代码中的语法/逻辑错误,提升代码健壮性。
二、核心知识点铺垫
1. 因子定义
若整数 a % b == 0(b ≠ 1),则称 b 是 a 的因子。
例如:60的因子有2、3、4、5、6、10等(1不算因子)。
2. 连续因子
指一组依次连续 的整数,且每个数都是目标数的因子。
例如:60的最长连续因子是 2 3 4 5 6。
3. 遍历优化思路
连续因子的起始数无需遍历到 n,只需遍历到 √n:
- 若起始数
i > √n,则i * (i+1) > n(两个连续数的乘积已超过n),无法形成长度≥2的连续因子; - 此优化可大幅减少循环次数,提升程序效率。
三、原代码分析(标注问题)
c
#include <stdio.h>
#include <math.h>
int main() {
int n;
// 输入目标整数
scanf("%d", &n);
int max_len=0; // 记录最长连续因子的长度
int start=n; // 记录最长连续因子的起始数
// 外层循环:遍历所有可能的起始因子(优化到√n)
for(int i=2;i<=sqrt(n);i++)//找连续因子在平方根的范围里判断
{
int temp=n; // 临时保存n,避免修改原数
int len=0; // 记录当前连续因子的长度
int current=i; // 当前判断的因子(从起始数i开始)
// 【错误1】中文括号")",编译报错;【错误2】缺少temp /= current,逻辑错误
while(temp%current==0)//通过循环,来找最长的长度
{
len++;
current++;
}
// 更新最长连续因子的起始数和长度
if(len>max_len)
{
start=i;
max_len=len;
}
}
// 输出最长连续因子
for(int i=0;i<max_len;i++)
{
printf("%d ",start+i); // 【错误3】最后一个数后多一个空格,格式不规范
}
return 0;
}
原代码核心问题总结
| 错误类型 | 具体问题 | 影响 |
|---|---|---|
| 语法错误 | while(temp%current==0) 中是中文右括号 |
编译失败,无法运行 |
| 逻辑错误 | 缺少 temp /= current |
无法正确判断"连续因子"(temp始终是原数n,导致判断结果错误) |
| 边界错误 | 未处理"质数"情况(如输入7,max_len=0,无输出) | 质数无连续因子时,应输出自身,原代码无输出 |
| 格式错误 | 输出最后多一个空格 | 不符合题目输出规范 |
四、修正后的完整代码(带详细注释)
c
#include <stdio.h>
#include <math.h>
int main() {
int n;
// 1. 输入目标整数
scanf("%d", &n);
// 初始化变量:
int max_len = 0; // 记录最长连续因子的长度(初始为0)
int start = n; // 记录最长连续因子的起始数(默认n,处理质数情况)
// 2. 外层循环:遍历所有可能的起始因子(优化到√n)
for (int i = 2; i <= sqrt(n); i++) {
int temp = n; // 临时变量:保存n的副本,避免修改原数
int len = 0; // 临时变量:记录当前连续因子的长度
int current = i;// 临时变量:当前判断的因子(从i开始)
// 3. 内层循环:判断从current开始的连续数是否都是temp的因子
while (temp % current == 0) { // 中文括号修正为英文)
len++; // 连续长度+1
temp /= current; // 核心修正:temp除以当前因子,继续判断下一个数
current++; // 下一个连续数
}
// 4. 更新最长连续因子的信息
if (len > max_len) {
start = i; // 更新起始数
max_len = len; // 更新最长长度
}
}
// 5. 输出结果:
for (int i = 0; i < max_len; i++) {
printf("%d", start + i); // 先输出数字
if (i != max_len - 1) { // 最后一个数不输出空格
printf(" ");
}
}
// 处理质数(无连续因子):输出自身
if (max_len == 0) {
printf("%d", n);
}
return 0;
}
五、代码逐行详解
1. 头文件
c
#include <stdio.h> // 输入输出函数(scanf/printf)
#include <math.h> // 数学函数(sqrt求平方根)
2. 输入与变量初始化
c
int n;
scanf("%d", &n); // 读取输入的整数n
int max_len = 0; // 最长连续因子长度,初始为0
int start = n; // 最长连续因子起始数,默认n(应对质数)
3. 外层循环(遍历起始因子)
c
for (int i = 2; i <= sqrt(n); i++) {
int temp = n; // 临时保存n,避免修改原数
int len = 0; // 当前连续因子长度
int current = i;// 当前判断的因子(从i开始)
// ... 内层循环 ...
}
- 起始数从2开始(1不算因子);
- 终止条件
i <= sqrt(n):优化遍历范围,减少计算量。
4. 内层循环(判断连续因子)
c
while (temp % current == 0) {
len++; // 连续长度+1
temp /= current; // 关键:temp除以当前因子,确保下一个数是剩余数的因子
current++; // 检查下一个连续数
}
- 例:n=60,i=2时:
- temp=60,current=2 → 60%2==0 → len=1,temp=30,current=3;
- temp=30,current=3 → 30%3==0 → len=2,temp=10,current=4;
- temp=10,current=4 → 10%4≠0 → 循环结束(原代码因缺少temp/=current,会错误判断到current=7)。
5. 更新最长序列
c
if (len > max_len) {
start = i;
max_len = len;
}
- 若当前连续长度超过已记录的最长长度,更新起始数和最长长度。
6. 输出结果
c
for (int i = 0; i < max_len; i++) {
printf("%d", start + i);
if (i != max_len - 1) {
printf(" ");
}
}
if (max_len == 0) { // 质数无连续因子,输出自身
printf("%d", n);
}
- 循环输出从
start开始的max_len个连续数; - 最后一个数不输出空格,符合格式要求;
- 质数(max_len=0)时,输出自身。
六、示例演示(输入60)
执行过程关键步骤:
- 输入n=60,max_len=0,start=60;
- 外层循环i=2:
- temp=60,current=2 → 60%2==0 → len=1,temp=30,current=3;
- temp=30%3==0 → len=2,temp=10,current=4;
- temp=10%4≠0 → 循环结束,len=2 > max_len(0) → start=2,max_len=2;
- 外层循环i=3:
- temp=60%3==0 → len=1,temp=20,current=4;
- temp=20%4==0 → len=2,temp=5,current=5;
- temp=5%5==0 → len=3,temp=1,current=6;
- temp=1%6≠0 → len=3 > max_len(2) → start=3,max_len=3;
- 继续遍历到i=√60≈7,最终找到最长序列起始数2,长度5;
- 输出:2 3 4 5 6。
七、关键注意事项
- 语法细节:编程时需区分中英文符号(括号、分号、逗号等),中文符号会导致编译错误;
- 逻辑核心 :
temp /= current是判断连续因子的关键,若缺少此步,无法正确缩小判断范围; - 边界处理:必须考虑"质数"的特殊情况(无连续因子,输出自身);
- 格式规范:输出时避免最后一个数后多空格,符合题目要求。
八、总结
- 最长连续因子问题的核心是双层循环:外层遍历起始因子(优化到√n),内层判断连续因子;
- 关键逻辑:通过
temp /= current确保连续数都是剩余数的因子; - 易错点:中文符号、缺少核心赋值、未处理质数边界、输出格式不规范。