2019-05-26  2024-09-15    3103 字  7 分钟

每个合数都可以写成几个质数相乘的形式,其中每个质数都是这个合数的质因数。如果一个质数是某个数的因数,那么就说这个质数是这个数的质因数。而这个因数一定是一个质数。

把一个合数用质因数相乘的形式表示出来,叫做分解质因数。如30=2×3×5 。分解质因数只针对合数。

质数: 质数(prime number)又称素数,有无限个。

质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。

合数: 合数指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数。与之相对的是质数,而1既不属于质数也不属于合数。最小的合数是4。其中,完全数与相亲数是以它为基础的。

定义

质因数(或质因子)在数论里是指能整除给定正整数质数。两个没有共同质因子的正整数成为互质。因为1没有质因子,所以1与任何正整数(包括自身)都是质数。正整数的因数分解可将正整数表示为一连串的质因子相乘,质因子如重复可以质数表示。根据算数基本定理,任何正整数皆有独一无二的质因子分解式。只有一个质因子的正整数为质数。

把一个合数分解成若干个质因数的乘积的形式,即求质因数的过程叫做分解质因数。

分解质因数只针对合数。(分解质因数也称分解素因数)求一个数分解质因数,要从最小的质数除起,一直除到结果为质数为止。分解质因数的算式叫短除法,和除法的性质差不多,还可以用来求多个个数的公因式。

例子

  • 1没有质因子
  • 5只有1个质因子,5本身。(5是质数)
  • 6的质因子是2和3(6=2*3)
  • 2、4、8、16等只有一个质因子:2(2是质数, $math_inline$4=2^2$math_inline$ , $math_inline$8=2^3$math_inline$ ,如此类推)
  • 10有两个质因子:2和5.(10=2*5)

就是一个数的约数,并且是质数,比如 $math_inline$8=2 * 2 * 2$math_inline$ ,2就是8的质因数。 $math_inline$12=2 * 2 * 3$math_inline$ ,2和3就是12的质因数。把一个式子以 $math_inline$12=2 * 2 * 3$math_inline$ 的形式表示,叫做分解质因数。 $math_inline$16=2 * 2 * 2 * 2$math_inline$ ,2就是16的质因数,把一个合数写成几个质数相乘的形式表示,这也是分解质因数。

分解质因数的方法是先用一个合数的最小质因数去除这个合数,得出的数若是一个质数,就写成这个合数相乘形式;若是一个合数就继续按照原来的方法,直至最后是一个质数。

分解质因数有两种方法表示,除了大家最长知道的“短除法”之外,还有一种方法就是“塔形分解法”。

分解质因数对解决一些自然数和乘积的问题有很大的帮助,同时又为最大公约数和最小公倍数做了重要铺垫。

计算方法

短除法

求一个数的分解质因数,要从最小的质数除起,一直除到结果为质数为止。分解质因数的算式叫短除法,和除法性质差不多,还可以用来求多个个数的公因式:

求最大公因数的一种方法,也可以用来求最小公倍数。

求几个数最大公因数的方法,开始时用观察比较的方法,即:先把每个数的因数找出来,然后再找出公因数,最后在公因数中找出最大公因数。

例如:求12与18的最大公因数。

  • 12的因数有:1、2、3、4、6、12
  • 18的因数有:1、2、3、6、9、18
  • 12与18的公因数有:1、2、3、6
  • 12与18的最大公因数是6

这两种方法对求两个以上数的最大公因数,特别是数目较大的数,显然是不方便的。于是又采用了给每个数分别分解质因数的方法。

  • $math_inline$12=2 * 2 * 3$math_inline$
  • $math_inline$18=2 * 3 * 3$math_inline$

12与18都可以分成几种形式不同的乘积,但分解质因数连乘积就只有以上一种,而且不能再分解了。所分出的质因数无疑都能整除原数,因此这些质因数也都是原数的约数。从分解的结果来看,12与18都有公约数2和3,而他们的乘积2*3=6,就是12与18的最大公约数。

采用分解质因数的方法,也就是采用短除的形式,只不过是分别短除,然后再找公约数和最大公约数。如果吧这两个数合在一起短除,则更容易找出公约数和最大公约数。

从短除中不难看出,12和18都有公约数2和3,他们的乘积2*3=6就是12与18的最大公约数。与前边分别分解质因数相比较,可以发现:不仅结果相同,而且短除法竖式左边就是这两个数的公共质因数,而两个数的最大公约数,就是这两个数的公共质因数的连乘积。

实际应用中,是吧需要计算的两个或多个数放置在一起,进行短除。

在计算多个数的最小公倍数时,对其中任意两个数存在的约数都要算出,其它无此约束的数则原样落下。最后把所有约数和最终剩下无法约分的数连乘即得到最小公倍数。

只含有一个质因数的数一定是亏数。(在数论中,若一个正整数除了本身之外所有因子之和比此数自身小,则称此数为亏数(又称作缺数)。)

短除法详解:

短除富豪就是除号倒过来。短除就是在除法中写余数的地方写两个数共有的质因数,然后落下两个数被共有质因数整除的商,之后再除,以此类推,直到结果互质为止(两个数互质)

而在用短除法计算多个数时,对其中任意两个数存在的因数都要算出,其它没有这个因数的数则原样落下。直到剩下每两个数都是互质关系。

求最大公因数乘一边,求最小公倍数乘一圈。

在用短除计算多个数时,对其中任意两个数存在的因数都要算出,其它没有这个因数的数则原样落下。直到剩下每两个都是互质关系。**求最大公约数遍乘左边所有数公共的因数,求最小公倍数遍乘一圈。**这种方法对求两个以上数的最大公因数,特别是数目较大的数,显然是不方便的。于是又采用了给每个数分别分解质因数的方法。

Pollard Rho因数分解

1975年,John M. Pollard提出了第二种因数分解的方法,Pollard Rho快速因数分解。该算法时间复杂度为 $math_inline$O(n^{(1/4)})$math_inline$ 。

将一个正整数分解质因数。例如:输入90,打印出 $math_inline$90=2 * 3 * 3 * 5$math_inline$ 。 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:

  1. 如果这个质数恰好等于n,则说明分解质因数的过程已经结束,打印出即可。
  2. 如果n<>,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数n,重复执行第一步。
  3. 如果n不能被k整除,则用k+1作为k的值,重复执行第一步。
//将一个数n分解为若干个从小到大排列的质数的积
void f1(int n) {
    cout << n << " = ";
    int n2 = n;
    if (n < 2) {
        cout << "ERROR" << endl;
    }  //小于2的数不合法,若n为质数则输出它本身
    for (int i = 2; i * i <= n2; i++) {  //根号n复杂度
        while (n2 % i == 0) {
            n2 = n2 / i;
            cout << i;
            if (n2 != 1) cout << "*";
        }
    }
    if (n2 != 1) cout << n2;  //当n为质数
    cout << endl;
}

void f2(int n) {
    cout << n << " = ";
    for (int i = 2; i <= n; i++) {
        while (n != i) {
            if (n % i == 0) {
                cout << i << '*';
                n = n / i;
            } else break;
        }
    }
    cout << n << endl;
}

void f3(ll n) {
    cout << n << '=';
    int flag = 0;
    for (ll i = 2; i * i <= n; i++) {
        while (n % i == 0) {
            n = n / i;
            if (!flag) cout << i;
            else cout << '*' << i;
            flag |= 1;
        }
    }
    if (n != 1 && !flag) cout << n << endl;
    else if (n != 1 && flag) cout << '*' << n << endl;
    else cout << endl;
}

另外代码:

我们用所有正整数试验一下,从2开始进行拭除,逐步增加除数的值,去寻找一个可以整除n的数。在Eratosthenes筛法的讨论中,我们知道如果n是一个复合数,那么它就会有一个素数 $math_inline$p\leq\sqrt{n}$math_inline$ 。

这个算法有两个循环路径,内部的和外部的。外部循环求唯一因数,内部循环求一个因数的多个复本。例如: $math_inline$24=2^3\times3$math_inline$ ,外部循环求出因数2和3.内部循环求出2是一个多因数。

void trial_divisio_fac(int n) {
    int a = 2;
    cout << n << "= ";
    while (a * a <= n) {
        while (n % a == 0) {
            cout << a << '*';
            n = n / a;
        }
        a++;
    }
    if (n > 1) cout << n;//n没有因数
    cout << endl;
}

上面的代码解释比较清楚。为什么这种方法可以得到素数。

因为我们在内层循环中,已经把当前a的所有倍数都去除了。这跟埃斯托尼算法一样的。

如果整数较小,这种情况下拭除法通常都是很有效的,但是如果用来分解更大的整数,拭除法就变得非常低效甚至不可用了。这种算法的复杂度是随着n的增加呈指数级别增长的。

拭除法整数分解算法中最简单和最容易理解的算法。

给定一个合数n(这里,n是待分解的整数),拭除法看成是用小于等于 $math_inline$\sqrt{n}$math_inline$ 的每个素数去拭除待分解的整数。如果找到一个数能够整除除尽,这个数就是待分解整数的因子。

运用拭除法求1233的因数

$math_inline$1233=3^2 * 137$math_inline$