目录
算数基本定理
算术基本定理可以表述为:对任意大于 (1) 的自然数,若不为质数,则一定能且只能写成一种有限个质数乘积的形式
或者可以表述为:对 (forall nin N) 且 (n>1) ,对所有的 (m) 个小于等于 (n) 质数 (p_{1cdots m}) ,(displaystyle n=prod_{i=1}^mp_i^{c_i},p_iin Prime,c_iin N) 存在且唯一存在
证明
我们用归纳法证明:考虑合数 (n) ,假设 (n) 以内的数要么都是质数,要么所有合数都符合上述定理
当 (n) 为最小的合数 (4) 时,(n=2 imes 2=2^2) 符合上述定理
其它情况下,因为 (n) 为合数,所以一定存在 (a,bin N) 且 (1<aleq b<n) 使得 (n=a imes b)
设一共有 (m) 个小于等于 (n) 的质数 (p_{1cdots m})
由于 (a<n) 因此 (a) 符合上述定理
故 (a) 可唯一地写作 (displaystyle a=prod_{i=1}^{m_a}p_i^{ca_i},p_iin Prime,c_iin N)
(ecause a<n)
( herefore m_aleq m)
( herefore a) 可唯一地写作 (displaystyle a=prod_{i=1}^{m_a}p_i^{ca_i}cdotprod_{i=m_a+1}^mp_i^0,p_iin Prime,c_iin N)
我们令 (d_i=egin{cases} ca_i,0<ileq m_a \ \ 0,m_a<ileq m end{cases})
故 (a) 可唯一地写作 (displaystyle a=prod_{i=1}^mp_i^{d_i},p_iin Prime,d_iin N)
同理,我们可以将 (b) 唯一地写作 (displaystyle b=prod_{i=1}^mp_i^{e_i},p_iin Prime,e_iin N)
因此 (n) 可唯一地写作 (displaystyle n=a imes b=prod_{i=1}^mp_i^{d_i}cdotprod_{i=1}^mp_i^{e_i}=prod_{i=1}^mp_i^{d_i+e_i},p_iin Prime,d_iin N,e_iin N)
令 (c_i=d_i+e_i) 因此,证得上述结论
综上,算术基本定理得证
质因数分解 (O(n))
由算数基本定理,我们得到,一个大于 (1) 的自然数,一定能分解为若干个质数的乘积
下面我们来具体考虑如何划分:
首先,定理的成立表明:对 (n) 以内的 (m) 个质数 (p_{1cdots m}) ,保证 (n=prod_{i=1}^mp_i^{c_i},p_iin Prime,c_iin N) 这一等式中的 (c_i) 都是唯一确定的
因此,将 (n) 划分为质数,即求出 (c_{1cdots m})
首先,十分显然:我们可以花费 (O(n)) 的时间筛出 (n) 以内的质数,然后一个一个去实验
int prime[MAXN],cntprime=0,c[MAXN]={0};
sieve_prime(int n){
...
}
...
sieve_prime(n);
int copy=n;
for(int i=1;i<=cntprime;i++){
if(copy%prime[i]!=0) continue;
while(copy%prime[i]==0){
copy/=prime[i];
c[i]++;
}
}
(n) 以内的质数个数大概 ({nover ln n}) 个,每个质因数被除的内存循环,复杂度为 (o(log n))
因此,分解的复杂度为 (o(n)) ,加上前面筛素数,总复杂度 (O(n))
优化 (O(sqrt n))
通过细心观察可以发现:对于大于等于 (sqrt n) 的质因数,一定不会存在超过一个
若存在两个大于等于 (sqrt n) 的质因数,设它们分别为 (p_a,p_b,p_aleq p_b)
单这两个质因数的乘积 (p_a imes p_bleq sqrt n imes sqrt n=n) 就注定了不可能同时是 (n) 的因数
因此大于等于 (sqrt n) 的质因数,一定不会存在超过一个
所以我们只需要花费 (O(sqrt n)) 将 (sqrt n) 以内的质数筛出来,然后重复上述操作
最后得到的如果是 (1) ,则代表没有大于 (sqrt n) 的质因数;否则,剩下的本身就是质因数
int prime[MAXN],cntprime=0,c[MAXN]={0};
sieve_prime(int n){
...
}
...
sieve_prime( (int)sqrt(n) );//或者在函数里面改为 i*i<=n
int copy=n;
for(int i=1;i<=cntprime;i++){
if(copy%prime[i]!=0) continue;
while(copy%prime[i]==0){
copy/=prime[i];
c[i]++;
}
}
if(copy!=1){
prime[++cntprime]=copy;
c[cntprime]++;
}
因为 (sqrt n) 以内的质数个数大概 ({sqrt nover ln{sqrt n}}={2sqrt noverln n}),每个质数的复杂度为 (o(log n))
因此分解的复杂度为 (o(sqrt n)) ,加上筛质数的复杂度
总复杂度 (O(sqrt n))