原理与步骤
问题分析
将正整数分解为质因数的乘积形式,如输入12,输出2^2 * 3。需要找到所有质因数并统计次数,按格式输出。
关键观察
- 质因数分解通过试除法实现,从最小的质数开始逐个试除。
- 每个质因数需除尽,统计次数。
- 输出时需处理乘号(首个因数前不加乘号,后续因数前加乘号)。
步骤
- 输入处理:读取待分解的正整数
n
。 - 质因数分解:
- 从
i=2
开始遍历到i*i <=n
。 - 若
n
能被i
整除,则统计i
的次数并除尽所有i
的因子。 - 输出
i
及其次数(如i^s
或i
)。
- 从
- 处理剩余质因数:若循环结束后
n
仍有剩余(大于1),说明剩余部分本身是质数,需输出。 - 格式控制:用标志变量
p
判断是否需要输出乘号。
图示法示例(以 n=12
为例)
- 初始状态:
a=12
,p=0
。 - 处理
i=2
:12%2=0
,统计次数s=2
,a=3
。- 输出
2^2
,p=1
。
- 处理
i=3
:3%3=0
,统计次数s=1
,a=1
。- 输出
*3
。
- 循环结束:
a=1
,不处理剩余部分。
最终输出:2^2 * 3
。
代码程序与注释
#include <iostream>
using namespace std;
int main() {
long long n, a;
int p = 0; // 标志变量,控制乘号输出
cin >> n;
a = n;
// 遍历可能的质因数,从2开始到i*i <=n
for (long long i = 2; i * i <= n; i++) {
if (a % i == 0) { // 发现质因数i
int s = 0;
while (a % i == 0) { // 除尽所有i的因子
a /= i;
s++;
}
// 输出格式处理
if (p) cout << "* ";
if (s != 1) cout << i << "^" << s << " ";
else cout << i << " ";
p = 1; // 标记已有因数输出
}
}
// 处理剩余质因数
if (a != 1) {
if (a != n) cout << "* " << a; // 分解后的剩余质数
else cout << a; // n本身是质数
}
return 0;
}
关键代码注释
-
循环条件
for (long long i = 2; i * i <= n; i++)
遍历可能的质因数,终止条件为
i^2 >n
。
问题:循环条件应为i*i <=a
以提高效率(原代码可能多循环)。 -
分解质因数
while (a % i == 0) { a /= i; s++; }
统计质因数
i
的次数并除尽。 -
输出格式控制
if (p) cout << "* ";
首个因数前不加乘号,后续因数前加乘号。
-
剩余质因数处理
if (a != 1) { ... }
若剩余部分为质数,需输出(如输入
7
直接输出)。
时间复杂度
- 最优情况:
O(sqrt(n))
,当n
是质数时需遍历到sqrt(n)
。 - 最坏情况:
O(sqrt(n))
,但因循环条件固定为i*i <=n
,可能多出冗余遍历。
总结
- 正确性:代码逻辑正确,能处理所有质因数分解情况。
- 效率问题:循环条件应为
i*i <=a
而非i*i <=n
,否则对大质数效率较低。 - 输出格式:通过标志变量
p
控制乘号,确保符合题目要求。 - 改进方向:优化循环条件为动态判断
i*i <=a
,减少不必要的遍历。