质因数分解

给一个数n,对他进行质因数分解

代码

for(int i = 2; i <= n; i ++)
    if(n % i == 0){
        cout << i << endl;
        while(n % i == 0) n /= i;
    }

证明以上循环可以输出n的所有质因数

  1. 当n为质数时,只输出n,得证。
  2. 当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;
}
原文地址:https://www.cnblogs.com/tomori/p/14236927.html