题目描述
所谓因子分解,就是把给定的正整数a,分解成若干个素数的乘积,即 a = a1 × a2 × a3 × … × an,并且 1 < a1 ≤ a2 ≤ a3 ≤ … ≤ an。其中a1、a2、…、an均为素数。
先给出一个整数a,请输出分解后的因子。
输入描述:
输入包含多组数据,每组数据包含一个正整数a(2≤a≤1000000)。
输出描述:
对应每组数据,以“a = a1 * a2 * a3…”的形式输出因式分解后的结果。
输入例子:
10
18
输出例子:
10 = 2 * 5
18 = 2 * 3 * 3
这一题我一开始的思路是先搞一个表存储1-1000000
的素数,然后从小到大进行穷举因数,应该也有不少道友也会这样想。
但是这里有一个潜在的数学规律,假设a合数,并且a == b * c
,其中b
、c
中必定有一个 ≤ sqrt(a)
,不可能出现b
、c
同时大于a
。
因此我们搜索的范围缩小为[2, sqrt(a)]
。
还有一点,当我们把a的所有2
因数都分解出来后,2的倍数(4、6、8...)
都不可能再分解出来,比如100
分解出2 x 2
后,无法再分出2的倍数,同样分解出所有3
因数后,则无法再分出3的倍数…
总结一下就是,在[2, sqrt(a)]
区间从小到大逐渐试探的时候,碰到一个分解的因数时a,就一直分解a,直到不能再分解a,此时也不可能再分解出a的倍数。
假设a
是素数,则a
的倍数(必定是合数)都被排除了试探,但是你如何保证a
就一定不是合数呢?也就是我们会担心分解出一个合数a
怎么办。
再回到我们得试探方法------
首先试探了2(素数),2的倍数被排除了,之后试探2的倍数绝对不会成功
接着试探了3(素数),3的倍数被排除了,之后试探3的倍数绝对不会成功
(不成功)试探4(2的倍数),如果此时还能整除4,那就能试探2了,自相矛盾。。。
试探了5(素数),5的本书被排除了,之后试探5的倍数绝对不会成功
....
依次类推,当我们在试探较小的素数时,已经排除了对应的倍数,
最终导致我们试探出的都是素数!!!
有一种找素数的方法称为筛选法
,比如让你找[1,100]之间的素数。
你只要在[2,100]
区间从小到大开始,拿到一个素数,就筛掉它的所有倍数。
比如拿了2
(素数),筛选掉2
的所有倍数,然后拿3
(素数),筛选掉3
的所有倍数,以此类推,最后你拿出的就是[1,100]
之间的所有素数。
#include <iostream>
#include <math.h>
using namespace std;
int main(int argc, const char * argv[]) {
int number = 0;
//scanf返回值为正确输入数据的变量个数,当一个变量都没有成功获取数据时,此时返回-1
while (scanf("%d", &number) != - 1) {
printf("%d = ", number);
//只需要从[2, sqrt(number)]试探即可
int maxEle = sqrt(number);
for (int i = 2; i <= maxEle; ++i) {
//如果能分解出i,则一直分解出i,直到不能再分解,这样可以避免分解出i的倍数(i的倍数一定是合数)
while (number % i == 0) {
if (i == number) {
//最后一个数之后不能输出*了,需要单独输出
//注意输出格式: 10 = 2 * 5
break;
}
printf("%d * ", i);
number /= i;
}
}
printf("%d\n", number);
}
return 0;
}