素数筛法(欧拉筛、埃氏筛)

本文详细介绍了两种常用的素数筛法——埃氏筛和欧拉筛。埃氏筛基于质数的倍数不是质数的原理,而欧拉筛则优化了这一过程,确保每个合数仅被其最小质因子筛去,提高了效率。两种筛法的时间复杂度分别为O(nlog^2_2n)和O(n),并提供了C语言的实现代码。此外,文章还提到可以使用std::bitset进行空间优化,并鼓励读者将筛法应用于其他问题的求解。
摘要由CSDN通过智能技术生成

一、埃氏筛

1.原理:

质数的倍数不是质数。

时间复杂度: O ( n l o g 2 2 n ) O(nlog^2_2n) O(nlog22n)
埃氏筛的时间复杂度不会证明,可戳别处

2.代码

int prm[255], prm_cnt;//存放素数的数组、素数个数
bool iscompos[255];//true代表为合数,false代表素数数
void make_prime(int n) {
	if (n <= 1)return;
	for (int i = 2; i <= n; i++) {
		if (iscompos[i] == 0) {
			prm[++prm_cnt] = i;
			for (int j = i * i; j <= n; j += i) {
				iscompos[j] = 1;
			}
		}
	}
	return;
}

二、欧拉筛

1.前言

埃氏筛中,例如21会被3、7同时筛去。

我们希望每个合数仅被筛去一次以提高效率。于是有了欧拉筛。

2.原理

每个合数仅被最小质因子/最大因数筛去

时间复杂度: O ( n ) O(n) O(n)
每个数仅被处理一次故时间复杂度为 O ( n ) O(n) O(n)

3.代码

//时间复杂度:O(n)
int prm2[maxn], cnt2, tab2[maxn];
void make_prime2(int x) {
    if (x <= 1)return;
    for (int i = 2; i <= x; i++) {
        if (!tab2[i])
            prm2[++cnt2] = i;
        for (int j = 1; j <= cnt2 && prm2[j] * i < x; j++) { // 枚举素数,筛去倍数
            tab2[i * prm2[j]] = 1;
            if (!(i % prm2[j])) // 当前数为该素数的倍数,即 prm[j] 为最小质因子
                break;    
        }
    }
}

一些后话

  • 无论是埃氏筛还是欧拉筛,都可以用 std::bitset 来缩小空间,提高速度(据说bitset 不能优化欧拉筛,反而负优化,但空间确实要小很多)
  • 筛法思想也可用于一些题目的求解,希望同学们不仅仅只会筛素数。
    例如:洛谷P2926 洛谷P7788

朝花夕拾喵~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值