Eular质数筛法 欧拉筛

Eular质数筛法 欧拉筛

相比于时间复杂度为 O(n(lgn)2) 的埃氏筛法,Eular 质数筛法就显得非常短小精悍

欧拉筛的时间复杂度为 O(n),是一种空间换取时间的算法

一、空间需求

欧拉筛需要两个数组:

① prime[],用来存储素数。

② is_prime[],用来表示 i (i <= n) 是否为质数。

二、步骤

① memset(is_prime, 1, sizeof(is_prime))

将 is_prime 数组全部置为 1。

② 外层循环LOOP:for( i = 2 -> n)

遍历每个数字 i 。

③ 若 i 为质数,那么将 i 加入 prime[] 数组。

④ 内层循环LOOP:for(j = 0 -> prime.length)

不论 i 是否为质数都会进入内层循环。

⑤ 若 i * prime[j] > n 则 break 内层循环LOOP。

否则,is_prime[ i * prime[j] ] = 0

把 i * prime[j] 标记为合数。

若 i % prime[j] == 0 则 break 内层循环LOOP,继续外层循环LOOP。

三、核心

欧拉筛效率这么高的核心就在于上面的第⑥点,

若 i % prime[j] == 0 则退出内层循环LOOP。

为什么可以直接退出呢?后面的数就不用继续筛选了吗?

是的,当 i % prime[j] == 0 时,说明 i = prime[j] * k

对于 prime[j] 后面的元素 prime[next_j],

prime[next_j] * i 将会在之后的筛选中被筛掉,无需重复。

因为 prime[next_j] * i = prime[next_j] * (prime[j] * k)

= prime[j] * (prime[next_j] * k)

例如:

prime[] = {2, 3} i = 4

2*4 = 8 被筛 此时 4%2 == 0 break

3*4 = 12 这次不筛

因为 4 = 22, 故 3 * (22) = 2 * (3*2)

在 3 * 2 = 6 = i 时会筛掉12。

参考代码:

int *prime;
int *is_prime;

void getPrime(int n){
	for(int i = 0; i <= n; i++){
		is_prime[i] = 1;
	}
	int cnt = 0;
	for(int i = 2; i <= n; i++){
		if(is_prime[i]){
			prime[cnt++] = i;
		}
		for(int j = 0; j < cnt; j++){
			if(prime[j]*i > n){
				break;
			}
			is_prime[prime[j]*i] = 0;
			if(i%prime[j] == 0){
				break;
			}
		}
	}
}

【END】感谢观看

发布了44 篇原创文章 · 获赞 17 · 访问量 9115

猜你喜欢

转载自blog.csdn.net/qq_41765114/article/details/88391427