质因数分解

给一个数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(k\ge 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;
}
posted @ 2021-01-05 17:11  yys_c  阅读(262)  评论(0编辑  收藏  举报