算法 素数筛法

本文介绍了素数筛法的关键思想,通过举例说明如何筛选素数,详细分析了算法的复杂度,并探讨了优化策略,包括避免重复筛选和数组大小优化。此外,还提及了进阶的素性测试算法,如费马测试、Miller-Rabin测试等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

素数筛法

关键思想

素数筛法是ACM 及各大比赛中必须熟练掌握的最低级的算法,在已知某些素数的情况下对未判断的数进行筛选,筛选掉必然不是素数的数。如何对数进行筛选,依据素数的性质,某个除1以外的正整数是素数,则该数的倍数一定不是素数

举个栗子

从1-10中筛选出所有素数

步骤当前元素12345678910
原始数组//000000000
第一步2/001010101
第二步3/001010111
第三步5/001010111
第四步7/001010111

以第一步为例:当前元素为2,则将22=423=625=10都置为合数,即每次都将当前为素数的元素的倍数从候选的数中除去。
循环上述过程,则可得到最终的数组,数组中为0的则该元素为素数,否则为合数。

代码如下

#include <cstdio>
#define MAXN 11
int prime[MAXN] = {1, 1}; //第0,1个元素直接设为合数,合数设为1,素数为0
int main() {
    //素数筛法求素数
    for (int i = 0; i < MAXN; ++i) {
        if (!prime[i]) {//若该数是素数,则将该数的倍数全设为合数。
            //printf("%d ",i); 答应当前元素
            for (int j = 2 * i;  j <= MAXN; j+=i) {//筛选掉必然是合数的数
                prime[j] = 1;
            }
        }
    }
    return 0;
}

复杂度

该算法的复杂度为O(n2),但常系数非常小,实际运行时接近O(N)复杂度,并且随着筛选的进行,可以仔细思考一下,最后筛选掉的数越来越多,剩下的素数越来越小,即素数之间的间隔越来越大。

关于优化

在素数筛法的过程中,有许多重复计算的过程可以进行优化,例如上述例子中,元素6和元素10都筛选了两次,就是表格中红了两次。
下边列一下可以优化的点,就不具体实现了。
1. 避免重复筛选
2. 偶数直接可以不参与筛选,并且依据这个规则可以将数组大小优化掉一半
说明一下第二点可以优化空间的方法,例如原数组的第i个元素代表数字i是否为素数,若直接将偶数去除,则数组的第i个元素则可代表数字2i1是否为素数。

进阶

想继续学习素数有关知识的可以看看以下几个知识点

  1. 费马测试
  2. Miller-Rabin 质数测试
  3. 欧拉-雅科比测试
  4. AKS质数测试

等等素性测试算法,可能以后会在详细讨论这些算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值