在“质数的筛选”中提到过算术基本定理,即任意一个大于
1
1
1的正整数都能唯一分解为有限个质数的乘积
所以可以使用试除法
O
(
n
)
O(\sqrt n)
O(n)来实现质因数分解
操作很简单,从最小的质数
2
2
2开始,一直到
n
\sqrt n
n,只要可以整除当前的数,就一直除以这个数,直到不能整除。
For example:
初始的
n
n
n为
120
120
120,i从
2
2
2循环到
n
\sqrt n
n
n
n
n可以整除
2
2
2,此时
n
=
60
n=60
n=60
n
n
n可以整除
2
2
2,此时
n
=
30
n=30
n=30
n
n
n可以整除
2
2
2,此时
n
=
15
n=15
n=15
n
n
n不能整除
2
2
2,
i
+
+
i++
i++
n
n
n可以整除
3
3
3,此时
n
=
5
n=5
n=5
n
n
n不能整除
3
3
3,
i
+
+
i++
i++
n
n
n不能整除
4
4
4,
i
+
+
i++
i++
n
n
n可以整除
5
5
5,此时
n
=
1
n=1
n=1
n
=
1
n=1
n=1,结束循环
观察我们除以过的数字,分别是
2
,
2
,
2
,
3
,
5
2,2,2,3,5
2,2,2,3,5
所以
120
=
2
×
2
×
2
×
3
×
5
120=2\times2\times2\times3\times5
120=2×2×2×3×5
来解释一下这个思路里的一些细节问题
1.循环到
n
\sqrt n
n的原因,还是像0x31 T1中提到的,如果
n
n
n不为质数,那
n
n
n就会有除了自己和
1
1
1以外的因数,假设这个因数为
i
i
i, 那么
n
/
i
n/i
n/i也一定是
n
n
n的因数,
i
i
i和
n
/
i
n/i
n/i之间一定就会有一个数
≤
n
\leq \sqrt n
≤n,所以只需要扫描到
n
\sqrt n
n,就可以找到除了
1
1
1和
n
n
n以外是否有其他的因数,即
n
n
n是否为质数,满足我们寻找n的质因子的目的。
2.对于每一个
i
i
i 都进行整除的操作,是否会有为合数的i被统计为质因数?答案是不会的,上面的例子中,
120
120
120可以整除
4
4
4,但当
i
=
4
i=4
i=4时,
n
n
n就已经变为了
5
5
5,已经不能整除
4
4
4了,出现这种情况的原因是,
4
4
4作为一个合数,也可以进行质因数分解,例如把
4
4
4分解为
2
×
2
2\times 2
2×2,所以
n
/
4
n/4
n/4就等价于
n
/
2
/
2
n/2/2
n/2/2,当
i
=
2
i=2
i=2时,我们就已经把所有的质因子
2
2
2都提出来了,因此当
i
i
i 为合数时,
n
n
n一定不会整除
i
i
i
3.
n
n
n的值是否可以一直改变?是的,因为我们要找的始终是现在的
n
n
n的质因子,所以
s
q
r
t
(
n
)
sqrt(n)
sqrt(n)也在一直改变。
code
int p[maxn],c[maxn];//p为底数,c为指数
void zhiyinshufenjie(int n)
{
int m=0;//计数器
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)//如果可以整除i
{
p[++m]=i;//底数为i
while(n%i==0) n/=i,c[m]++;//指数+1
}
}
if(n>1) //n现在自身为质数
{
p[++m]=n;
c[m]++;
}
for(int i=1;i<=m;i++) cout<<p[i]<<' '<<c[i]<<endl;
}