🔒 题目描述
给定一个正整数 a i a_i ai,将 a i a_i ai分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。
例如
输入样例
6
输出样例
2 1
3 1
输入样例
8
`输出样例
2 3
🎃知识补充
1.算术基本定理
1.1 内容
如果不考虑排列次序的话,每个大于1的自然数都只能有一种方式分解成若干个(大于等于1个)素数的乘积。
1.2 性质
1.(存在性)每个大于1的自然数都可以分解成素数的乘积。
2.(唯一 性)这种分解,在不考虑排 列次序的意义下,是唯一的。
1.3 推论
1.如果素数p整除两个整数a和b的乘积ab,则p必然会整除a或b。
2.两个大于1的数的乘积等于它们最小公倍数和最大公约数的乘积。
2.什么是素因数分解(质因数分解)?
将一个正整数表示成素因数乘积的过程和得到的表示结果叫做素因数分解
注意这里叫法略微不同,不过意思都相同。也可以叫做分解质因数或者分解素因数。
3.重要结论
刚才说了正整数 a i a_i ai在分解质因数的时候,可以被质因数唯一地分解。另外还有一条重要结论就是 : : :在正整数被分解完后的质因数表达式中,这些质因数最多只有一个的值是大于 a i \sqrt{a_i} ai的。
证明:
可以想一下:如果要是在这个质因数表达式中,要是有两个质因数的值是大于 a i \sqrt{a_i} ai的,那么它俩乘起来的值就一定会大于 a i \sqrt{a_i} ai ,那么就不对了。
🔑 思路和代码
从2到$ a i \sqrt{a_i} ai 之 间 枚 举 所 有 的 数 字 , 然 后 统 计 之间枚举所有的数字,然后统计 之间枚举所有的数字,然后统计 a i a_i ai的因子的次数。
这里的思路一开始不太好解释,大家先看代码。看完代码之后,我再详细解释。
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
void divide(int num)
{
for(int i = 2; i <= num / i; ++i)//(3)
{
if (0 == num % i)//(4)
{
int count = 0;//(5)
while(0 == num % i)//(6)
{
num /= i;
count++;
}
printf("%d %d\n",i,count);
}
}
if (num > 1)//(7)
{
printf("%d %d\n",num,1);
}
}
int main()
{
int num;
scanf("%d",&num);//(1)
divide(num);//(2)
return 0;
}
-
输入一个待被分解的正整数 n u m num num
-
调用质因数分解函数 d i v i d e divide divide
-
枚举小于等于 n u m \sqrt{num} num部分的因子,这里可以类比质数的判定。
-
试图找到 n u m num num的因子。如果 n u m num num % i = = 0 i == 0 i==0,说明 i i i是 n u m num num的因子。
这里可能会有一个疑问 : : :这里枚举的话,不会不把合数也给枚举进去呢?
答案是不会的。因为假如枚举到某个i了,如果这个i是合数,那么i一定有除了1和它本身之外的其他因子,而且这些因子比i小。那么这些因子必然也是 n u m num num的因子。但是由于存在(6)这个语句,也就意味着在枚举到i的时候,在 n u m num num的因子中,小于 i i i的因子已经被全部枚举完了,是不会再出现的。但是这里 i i i是合数,也就意味着还存在着比 i i i小的因子,那么这是矛盾的。所以,这里能进去(4)的语句,就说明 i i i一定是质数。 -
count用来记录质因子的次数。
-
来得到质因子的次数,同时 n u m num num也在 " 削 减 " "削减" "削减"。因为 n u m num num在不断的除以质因子,这里类比法师不断地释放技能,那么法力条就会一直在削减(前提是法师没有各种加成,就一个单单的法力条)。
-
根据
重要结论
, n u m num num可能有大于 n u m \sqrt{num} num的质因子,也可能没有大于 n u m \sqrt{num} num的质因子。
如果没有的话,那么一定会在(6)那里一直除,直到x取值为1,然后退出。
如果有的话,那么会在(6)那里退出,而且此时的x就是最后的那个因子。最后的因子如果存在,那么一定是大于1的,所以输出。
写在最后
这节知识比较绕,很容易绕在里面,那么绕进去的话,不要害怕,多想一想,多用笔算一算,过段时间就会明白了。