给一个数n,对他进行质因数分解
代码
for(int i = 2; i <= n; i ++)
if(n % i == 0){
cout << i << endl;
while(n % i == 0) n /= i;
}
证明以上循环可以输出n的所有质因数
- 当n为质数时,只输出n,得证。
- 当n不是质数时。
对于2,用数学归纳法证明(注意i是全程自增的)
设(n)的初始值为(n_0),(t_i)为可以整除(n_i)的第一个数
(1)) 由于(t_0)为能够整除(n_0)的第一个数,可知(n_0)不存在(2 ,...,t_0 - 1)的约数,
又因为(n_0 \% t_0 = 0),所以(t_0)也不存在(2 ,...,t_0 - 1)的约数,所以(t_0)必为质数。
根据循环要求,将(n_0)中的(t_0)除完变为(n_1),(n)的值变为(n_1)。
(2)) 假设(t_k(kge 1))为素数,所以(t_k)不存在(2,...,t_k - 1)的约数,由于(n_k \% t_k = 0), 所以(n_k)也不存在(2,...,t_k - 1)的约数,所以将(n_k)中的(t_k)全部除完得到的(n_{k + 1})不存在(2,...,t_k)的约数,又因为(t_{k + 1})为第一个能够整除(n_{k + 1})的数,所以(t_k + 1, ...,t_{k+1} -1)中不存在(n_{k+1})的约数,所以(2,...,t_{k+1} - 1)中不存在(n_{k+1})的约数,又因为(n\%t_{k+1}=0),所以(t_{k+1})没有(2,...,t_{k+1} - 1)中的约数,所以(t_{k+1})为素数。
(3)) 获证当n不是素数时,在此循环中所有可以整除n的i均为素数。
由1和2,所以此循环可以输出n的所有质因子。
优化
原始代码复杂度为(O(n))。
首先证明一个结论:对于一个数n,最多含有一个(数量上,不是种类上)大于sqrt(n)的质因子。
证明:因为对于一个数n可对其质因数分解为(n = p_{1}^{k1}p_{2}^{k2}...p_{t}^{kt}),显然不可以存在两个及以上的大于sqrt(n)的质因子,如果存在两个及以上的大于sqrt(n)的质因子,必有(n <p_{1}^{k1}p_{2}^{k2}...p_{t}^{kt})。
所以质因子的枚举范围可以缩小为(2,...,[sqrt n]),最后需要特判一下n是否为1,若不为1,就要把n也输出。
复杂度:最好情况下(n = 2^k), 此时复杂度为(O(logn)),最坏情况下(O(sqrt n))
#include<iostream>
using namespace std;
int n;
void divide(int a){
for(int i = 2; i <= a / i; i ++){
if(a % i == 0){
int s = 0;
while(a % i == 0){
a /= i;
s ++;
}
cout << i << ' ' << s << endl;
}
}
if(a > 1) cout << a << ' ' << 1 << endl;
}
int main(){
cin >> n;
while(n --){
int a;
cin >> a;
divide(a);
puts("");
}
return 0;
}