欧拉筛法(全)

介绍

欧拉筛法(Euler’s Sieve),又称为线性筛法,是一种高效的素数筛选算法,其时间复杂度和空间复杂度都是线性的,可以在O(n)的时间和空间内完成筛选。欧拉筛法有效地避免了埃拉托斯特尼(Eratosthenes)筛法中重复的筛选,保证了每个数只被筛选一次,从而提高了筛选效率。

基本思想

欧拉筛法的基本思想是基于每个合数必然有其最小质因子,且每个合数只被其最小质因子筛选一次。算法从2开始,逐步枚举每个数,对于每个未被筛选的数,视为素数,并用它来筛选其后的数。在筛选过程中,如果一个数能被之前的某个素数整除,则停止用该素数及之后的素数进行筛选,因为该数已经被其最小质因子筛选过。

算法过程

  1. 初始化:将所有数标记为素数(或未筛选状态),通常使用一个数组来记录每个数的状态。
  2. 枚举:从2开始,逐个枚举每个数i。如果i未被筛选(即i是素数),则将其加入素数列表,并用i来筛选后续的数。否则,跳过i,继续枚举下一个数。
  3. 筛选:对于每个素数p(已加入素数列表),用p乘以i来筛选i的倍数。但需要注意,当i能被p整除时(即i是p的倍数),停止用p及之后的素数来筛选i的倍数,因为此时i的倍数已经被其更小的质因子筛选过。
  4. 重复:重复上述过程,直到枚举完所有数。

优点

  1. 线性时间复杂度:欧拉筛法的时间复杂度为O(n),适合处理大数据量的素数筛选问题。
  2. 不重复筛选:通过确保每个合数只被其最小质因子筛选一次,避免了重复筛选,提高了效率。

应用

欧拉筛法不仅用于筛选素数,还可以用于求解其他与素数相关的数论问题,如求1n之间所有自然数的欧拉函数φ(x)、求1n之间每个数的因子个数和因数和等。

示例代码(C++)

#include <iostream>  
#include <vector>  
#include <cmath>  
using namespace std;  
  
const int MAXN = 1000000; // 定义最大范围  
int prime[MAXN], is_prime[MAXN], cnt = 0; // prime用于存储素数,is_prime用于标记素数(0为素数,1为合数),cnt记录素数个数  
  
void euler_sieve(int n) {  
    for (int i = 2; i <= n; i++) {  
        if (!is_prime[i]) {  
            prime[cnt++] = i; // i是素数,加入素数列表  
        }  
        for (int j = 0; j < cnt && i * prime[j] <= n; j++) {  
            is_prime[i * prime[j]] = 1; // 标记i*prime[j]为合数  
            if (i % prime[j] == 0) break; // 如果i能被prime[j]整除,则停止筛选  
        }  
    }  
}  
  
int main() {  
    int n;  
    cout << "请输入一个正整数N:" << endl;  
    cin >> n;  
    euler_sieve(n);  
    cout << "N内的所有素数及个数如下:" << endl;  
    for (int i = 0; i < cnt; i++) {  
        cout << prime[i] << endl;  
    }  
    cout << "共有" << cnt << "个素数" << endl;  
    return 0;  
}
这段代码展示了如何使用欧拉筛法来筛选小于等于n的所有素数,并打印出这些素数及其个数。
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值