C++质因数分解
较难11拆数高手:学会用C++做质因数分解
什么是质因数分解?
你有没有玩过“拆积木”?把一个大的造型拆成几个小的标准积木块。质因数分解就像拆数字积木:把一个合数(比如12、30、100)拆成几个质数(比如2、3、5、7)相乘的形式。例如:
- 12 = 2 × 2 × 3
- 30 = 2 × 3 × 5
- 100 = 2 × 2 × 5 × 5
这些乘法右边的数字全是质数,而且不能再拆了。为什么要做这件事?因为质因数就像是数字的“基本粒子”,很多数学问题(比如求最大公约数、判断两个数是否互质)都要用到它。生活中也可以类比:你有一堆糖果(合数),要平均分给几个小朋友,每个小朋友只能拿到同一种糖果(质数),看看能分成几种。
预备知识:质数和合数
要搞懂质因数分解,先分清两种数字:
- 质数:只能被1和它自己整除的数,比如2、3、5、7、11……(1不是质数哦!)
- 合数:除了1和它自己,还能被别的数整除,比如4、6、8、9、12……
质因数分解的目标就是:把一个合数写成质数相乘的形式。注意:1既不是质数也不是合数,所以分解时也不考虑1。
分解原理:从最小的质数开始试
想象你有一块橡皮泥(合数),你想把它捏成几个小圆球(质数)。你会先试试最小的圆球模具(数字2),能压出来就压一次,剩下的橡皮泥再继续压。如果2不行(不能被2整除),就换下一个模具3,再不行换5、7……直到剩下的橡皮泥自己就是一个圆球(质数)为止。
用数学语言说:从质数2开始,检查当前的数 n 能否被 i 整除。如果能,就输出 i,然后把 n 除以 i,继续用同样的 i 再试(因为同一个质数可能乘多次,比如8=2×2×2)。如果不能整除,i 增加1,继续试。当 i × i > n 时,停止循环——此时如果 n > 1,那么剩下的 n 本身就是一个质因子。
为什么当 i × i > n 就可以停?因为如果 n 有大于 √n 的因子,那么它一定还有一个小于 √n 的因子,我们已经试过了。所以最后剩下的 n 只能是1或者一个质数。
代码一步一步实现
下面我们写一个函数,把分解过程用C++表达出来。注意每个变量都加上中文注释,让代码自己会说话。
#include <iostream>
using namespace std;
void factorize(int num) { // num: 要分解的合数
cout << num << " = ";
int n = num; // n: 当前剩余未分解的数
// 从最小的质数2开始试
for (int i = 2; i * i <= n; i++) { // i: 当前尝试的除数(质数)
while (n % i == 0) { // 如果n能被i整除
cout << i << " * "; // 输出这个质因子
n = n / i; // 除一次,得到新的n
}
}
// 循环结束后,如果n大于1,说明n本身是一个质因子
if (n > 1) {
cout << n;
}
cout << endl;
}
int main() {
int num; // 用户输入的数字
cout << "请输入一个正整数:";
cin >> num;
factorize(num);
return 0;
}
运行示例:
请输入一个正整数:12
12 = 2 * 2 * 3 *
咦,最后多了一个星号!这是因为我们在输出每个质因子时都加上了 " * ",最后一个因子后面也加了。这不太美观。我们可以改进一下:把因子先存到数组里,最后统一输出,或者用判断条件控制星号。下面给出一个更干净的版本。
优化版:去掉多余的乘号
#include <iostream>
#include <vector> // 用vector保存因子
using namespace std;
void factorize(int num) {
cout << num << " = ";
int n = num; // n: 当前剩余待分解的数
vector<int> factors; // factors: 存放所有质因子
for (int i = 2; i * i <= n; i++) { // i: 当前尝试的除数
while (n % i == 0) {
factors.push_back(i); // 把i加入因子列表
n = n / i;
}
}
if (n > 1) {
factors.push_back(n); // 最后的质因子
}
// 输出因子,用" * "连接
for (int j = 0; j < factors.size(); j++) {
if (j > 0) cout << " * ";
cout << factors[j];
}
cout << endl;
}
int main() {
int num; // 用户输入的数字
cout << "请输入一个正整数:";
cin >> num;
factorize(num);
return 0;
}
运行结果:
请输入一个正整数:12
12 = 2 * 2 * 3
干净整齐!如果数字本身是质数(比如13),输出为 13 = 13,分解结果就是它自己。
生活例子来巩固
例子1:分零食
你有一袋100颗的糖果,想分成相同的小包,每包必须装一样多的糖果,而且每包的数量必须是质数。那么100可以拆成:100 = 2 × 2 × 5 × 5,也就是你可以分成4包,每包25颗(25不是质数,所以不能停)——但实际分解时,我们要的是最细的拆法,也就是2、2、5、5,你可以把它们看作“小包”的规格:先分成2包50颗,再每包分成2包25颗,再……直到每包5颗,最后5颗不能再分了。
例子2:找密码
老师给了一个数字360,让你分解成质因数。360 = 2 × 2 × 2 × 3 × 3 × 5。这可以用来快速求因数个数:每个质数的指数加1再相乘。比如360的因数个数 = (3+1)×(2+1)×(1+1) = 4×3×2=24个。
新手常犯的错误
-
忘记循环条件
i * i <= n写成了i <= n这样会循环到很大,效率非常低,而且可能输出很多无意义的数字。记住,试到平方根就够了。 -
while循环里没有改变n 如果忘记写
n /= i,会陷入死循环,不停输出同一个因子。 -
把1当作质数 有的同学看到最后if(n > 1)输出n,但如果输入的是1,程序会输出
1 =然后什么也不显示。1不是合数也不是质数,不要对1做分解。 -
没有处理输入为负数或0 我们的代码只适用于正整数,如果输入负数或0,结果会混乱。可以加一个判断:
if (num <= 1) { cout << "请输入大于1的整数\n"; return; }
完整可运行的最终代码(含输入检查)
#include <iostream>
#include <vector>
using namespace std;
void factorize(int num) { // num: 要分解的数
if (num <= 1) {
cout << num << " 无法分解质因数" << endl;
return;
}
cout << num << " = ";
int n = num; // n: 当前剩余待分解的数
vector<int> factors; // factors: 存放所有质因子
for (int i = 2; i * i <= n; i++) { // i: 当前尝试的除数
while (n % i == 0) {
factors.push_back(i);
n = n / i;
}
}
if (n > 1) {
factors.push_back(n);
}
// 输出结果
for (int j = 0; j < factors.size(); j++) {
if (j > 0) cout << " * ";
cout << factors[j];
}
cout << endl;
}
int main() {
int num; // 用户输入的数字
cout << "请输入一个正整数(大于1):";
cin >> num;
factorize(num);
return 0;
}
你可以试试这些数字:
- 100 → 2 * 2 * 5 * 5
- 97 → 97 (质数,只输出自己)
- 36 → 2 * 2 * 3 * 3
- 2 → 2
继续探索
学会了质因数分解,你还可以挑战:
- 用质因数分解求两个数的最大公约数(取公共质因数的较小指数)
- 求最小公倍数(取所有质因数的较大指数)
- 判断一个数是不是质数(如果分解后只有它本身,就是质数)
- 更高效的方法:埃氏筛法先筛出所有质数,再用这些质数去分解,速度更快。
质因数分解是数论的基础,就像拆开乐高积木一样有趣。快去试试分解你学号、生日数字吧!
例题精讲
以下哪个是数字 24 的质因数分解结果?
用试除法对正整数 n(n>1)进行质因数分解时,循环的终止条件(即i的最大值)一般设为?
任何一个大于1的自然数都可以唯一地分解为质因数的乘积(不计相乘的顺序)。
以下函数使用试除法输出正整数 n 的质因数分解结果(每输出一个因子后用空格隔开,最后输出换行)。请在 ___ 处补全代码。
void factor(int n) {
for (int i = 2; ___; i++) {
while (n % i == 0) {
cout << i << " ";
___;
}
}
if (n > 1) cout << n << endl;
}下面的代码利用while循环对 n(n≥2)进行质因数分解,按“质因子^指数”的格式输出(如输出 2^3 * 3^1)。请在 ___ 处补全代码。
void factor_exp(int n) {
for (int i = 2; i * i <= n; i++) {
if (___ ) {
int cnt = 0;
while (n % i == 0) {
n /= i;
cnt++;
}
cout << i << "^" << cnt << " * ";
}
}
if (n > 1) cout << n << "^" << 1 << endl;
}