欧拉筛 素数打表

本文介绍如何使用欧拉筛法(线性筛)高效地找出一定范围内的所有素数。该方法的时间复杂度为O(n),通过从2开始标记每个质数的倍数来确定合数,确保每个合数仅被其最小的质因数筛一次。

当遇到需要求一定范围内的素数来使用时,可以使用欧拉筛法求出范围内全部的素数,且时间复杂度为O(n),也称线性筛。

代码如下

public List<Integer> getPrimes(int n){
        List<Integer> primes = new ArrayList<>();
        boolean st[] = new boolean[n+1];
        for(int i = 2; i <= n; i ++){
            if(!st[i]){
                primes.add(i);
            }
            for(int p : primes){
                if(p * i > n)
                    break;
                st[p * i] = true;
                if(i % p == 0){
                    break;
                }
            }
        }
        return primes;
    }

利用的思想即是每个质数的倍数都一定不是质数,因此可以从2开始向后标记,最后得到范围内全部的质数。
但为避免重复标记,通过 i % p == 0 实现每个合数都只被最小的质因数筛一次

i = 4时,此时primes = {2,3}
i * p = 8,8标记为合数,此时 4 % 2 == 0,即表示其后的合数可以用2筛去而非用4
即省略的筛是i = 4,p = 3,i * p = 12情况,12不必用4 * 3筛去,在后续处理中,12会由2筛去

i = 6时,此时primes = {2,3,5}
i * p = 12,12标记为合数,此时即实现了12是由它的最小质因数2筛去的,对于12只筛了一次

### Java实现欧拉筛法素数 #### 示例代码 以下是使用Java实现欧拉筛法(Eratosthenes筛法优化版)的示例代码: ```java import java.util.Arrays; public class EulerSieve { public static void sieveOfEuler(int max) { boolean[] isPrime = new boolean[max + 1]; // 标记数组,默认false表示未标记 Arrays.fill(isPrime, true); isPrime[0] = isPrime[1] = false; // 0和1不是素数 int count = 0; for (int i = 2; i <= max; i++) { if (isPrime[i]) { System.out.print(i + " "); // 找到一个素数i count++; // 将当前素数的所有倍数标记为合数 for (int j = i * 2; j <= max; j += i) { if (isPrime[j]) { // 防止重复标记,提升效率 isPrime[j] = false; } } } } System.out.println("\nTotal primes found: " + count); } public static void main(String[] args) { int upperLimit = 50; // 设置上限值 System.out.println("Primes up to " + upperLimit + ":"); sieveOfEuler(upperLimit); } } ``` --- #### 算法讲解 欧拉筛法是一种高效的算法用于寻找一定范围内的所有素数。其核心思想在于通过已知的素数逐步排除掉这些素数的倍数,从而得到剩余的素数集合。 1. **初始化** 创建一个布尔类型的数组`isPrime`,大小为给定的最大值加一。初始时假设所有的数都是素数(即设置为`true`),除了0和1以外[^3]。 2. **遍历与标记** 对于每个尚未被标记为合数的数`i`,将其视为素数并打印出来或存储起来。接着,将该素数的所有倍数逐一标记为合数(即将对应的`isPrime[j]`设为`false`)。为了避免重复标记某些相同的合数,可以加入额外判断条件以跳过已经处理过的数值组合。 3. **时间复杂度分析** 欧拉筛法的时间复杂度接近线性级别\(O(n)\),相较于传统的暴力枚举方法显著提高了性能。这是因为每个合数只会由它的最小质因数负责删除一次。 4. **空间复杂度分析** 使用了一个长度为`max+1`的辅助数组来记录状态信息,因此空间复杂度为\(O(n)\)。 --- #### 注意事项 虽然上述代码实现了基本功能,但在实际应用中可能还需要考虑边界情况以及更大规模的数据输入场景下的内存占用等问题。此外,在更高级的应用场合下,比如密码学领域中的RSA加密技术,则会涉及到更加复杂的数学理论支持及其具体实现细节[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值