#数论# 快速分解质因数的技巧 && 筛法求素数(快速筛)

版权声明:本文为博主原创文章,转载清注明出处 https://blog.csdn.net/Jasmineaha/article/details/82749254

快速分解质因数

在做题时经常遇到要分解质因数,那么如何快速分解质因数呢?

在用筛法求素数时,我们使用线性筛的方法,并在每次筛的过程中,记录下每个数的最小质因数。那么在分解质因数的时候,只需要不断除以当前数的最小质因数,就可以快速得到分解的质因数了。

给出一个简单的例子,比如我们要求 50 这个数的质因数:

首先,利用线性筛找到所有的素数,并记录非素数的最小质因数,然后再将数字 50 除以他的最小质因子(也就是2)得到 25,然后再将数字 25 除以他的最小质因子(也就是5)得到 5,到这为止就做完啦,50 的质因数就是 2 和 5。

筛法求素数

一般的线性筛法

这种方法比较好理解:初始时,假设全部都是素数,当找到一个素数时,显然这个素数乘上另外一个数之后就一定是合数(注意上面的 i*i , 比 i*2 要快点 ),把这些合数都筛掉,即算法名字的由来。 但仔细分析能发现,这种方法会造成重复筛除合数,影响效率。比如10,在 i = 2 的时候,k = 2*15 筛了一次;在 i=5,k=5*6 的时候又筛了一次。所以,也就有了快速线性筛法。

void make_prime()
{
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = 0;
    for(int i = 2;  i < n;  i++) {
        if(prime[i]) {
            primes[++cnt] = i;
            for(int j = i * i; j < n; j += i)
                prime[j] = 0;
        }
    }
    return;
}

快速线性筛法

快速线性筛法没有冗余,不会重复筛除一个数,所以“几乎”是线性的,虽然从代码上分析,时间复杂度并不是O(n)。

void GetPrime() {
    for(int i = 2; i < n; i++) {
        if(!NotPrime[i]) prime[num_prime++] = i;
        for(int j = 0; j < num_prime && i * prime[j] < n; j++) {
            NotPrime[i*prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Jasmineaha/article/details/82749254