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

快速分解质因数

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

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

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

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

筛法求素数

一般的线性筛法

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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)。

1
2
3
4
5
6
7
8
9
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;
}
}
}

你可能感兴趣的:(【数论】快速分解质因数的技巧 && 筛法求素数(快速筛))