题解:洛谷 P1075 质因数分解
【题目来源】
洛谷:P1075 [NOIP 2012 普及组] 质因数分解 - 洛谷(luogu.com.cn)
【题目描述】
已知正整数 \(n\) 是两个不同的质数的乘积,试求出两者中较大的那个质数。
【输入】
输入一个正整数 \(n\)。
【输出】
输出一个正整数 \(p\),即较大的那个质数。
【输入样例】
21
【输出样例】
7
【核心思想】
-
问题分析:给定一个正整数 \(n\),它是两个不同质数的乘积。要求找出这两个质数中较大的那个。由于 \(n\) 的质因数只有两个,因此本题的实质是寻找 \(n\) 的最小质因数,较大的质因数即为 \(n\) 除以该最小质因数。
-
算法选择:
- 试除法找最小质因子:从 \(2\) 开始递增枚举整数 \(i\),第一个能整除 \(n\) 的 \(i\) 一定是较小的那个质数。此时较大的质数即为 \(n / i\)。由于 \(n\) 是两个质数的乘积,因此较小的质数一定不超过 \(\sqrt{n}\),所以枚举到 \(\sqrt{n}\) 即可,无需判断 \(i\) 和 \(n/i\) 是否为质数(因为题意保证 \(n\) 是两个质数的乘积,故找到的因子必为质数)。
- 复杂度优化:只需遍历到 \(\sqrt{n}\),无需对因子进行额外的素数判定。
-
关键步骤:
- 读入:读取正整数 \(n\)。
- 枚举:从 \(i = 2\) 开始,依次检查 \(i\) 是否能整除 \(n\)。
- 若能整除(即 \(n \% i == 0\)),则 \(i\) 就是较小的质数,较大的质数为 \(n / i\),直接输出并结束程序。
- 若不能整除,则 \(i\) 自增继续尝试。
- 输出:输出较大的质数 \(n / i\)。
-
时间/空间复杂度:
- 时间复杂度:\(O(\sqrt{n})\),最坏情况下需要遍历到 \(\sqrt{n}\),对于 \(n \le 2\times 10^9\) 是可行的。
- 空间复杂度:\(O(1)\),仅使用常数个变量。
-
数学性质简化:
- 算术基本定理:任何大于 1 的整数都可以唯一分解为质数的乘积。题目保证 \(n\) 是两个不同质数的乘积,因此 \(n\) 的质因数分解形式唯一为 \(n = p \times q\),其中 \(p < q\) 且均为质数。
- 因子对称性:\(p\) 一定是 \(n\) 的所有大于 1 的因子中最小的那一个。因此,从 2 开始递增找到的第一个因子就是 \(p\),无需遍历到 \(n\) 或进行额外的质数检测。
- 适用场景:这类根据唯一分解定理求解的简单质因数分解问题,核心是利用因子成对出现的性质,从最小因子入手,直接得出另一个因子。
【算法标签】
普及- #质数
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件
using namespace std;
// 判断素数的辅助函数
bool fun(int n) {
if (n <= 1) return false; // 1和负数不是素数
for (int i = 2; i < sqrt(n); i++) { // 只需检查到√n的范围
if (n % i == 0) return false; // 发现能整除的因子
}
return true; // 未发现因子则是素数
}
int main() {
int n; // 存储输入的正整数
cin >> n; // 读取输入
// 遍历2到n寻找满足条件的因子
for (int i = 2; i <= n; i++) {
if (n % i == 0) { // 如果i是n的因子
// 检查i和n/i是否都是素数
if (fun(i) && fun(n / i)) {
cout << n / i; // 输出较大的素数因子
break; // 找到后立即退出循环
}
}
}
return 0; // 程序正常结束
}
【运行结果】
21
7
浙公网安备 33010602011771号