素数的筛选方法

本文深入解析了埃氏筛法和欧拉筛法两种求素数的方法,详细阐述了它们的工作原理和算法优化,埃氏筛法通过标记合数筛选素数,而欧拉筛法则确保每个合数仅由其最小质因子筛选,避免重复。

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

一,埃式筛法
埃氏筛法是数学家埃拉托斯特尼所发明的一种比较稳定的求素数方法,他还可以顺带记录下来沿途的素数。
原理:用已经有的素数筛掉未来的非素数。
埃氏筛法的基本思想 :从2开始,将每个质数的倍数都标记成合数,以达到筛选素数的目的。

int slove(int n)
{
    int p=0;//用来记录素数的多少 
    for(int i=0;i<=n;i++)
        is_prime[i]=true;//先把它初始化
    is_prime[0]=is_prime[1]=false;//人为规定0,1不是素数 
    for(int i=2;i<=n;i++)//枚举 
    {
        if(is_prime[i])//如果它是素数
        {
            prime[p++]=i;//计算素数的个数,也记录下了素数
            for(int j=2*i;j<=n;j+=i)//用它去筛它的素数 
                is_prime[j]=false;//它的倍数自然不是质数 
        }
    }
    return p;//返回多少个素数 
}

其实这段代码还可以优化一下:将j 从 i * i 而不是从 i + i开始,因为 i*(2~ i-1)在 2~i-1时都已经被筛去,所以从i * i开始。
埃氏筛法的缺陷 :对于一个合数,有可能被筛多次。例如 30 = 2 * 15 = 3 * 10 = 5*6……那么如何确保每个合数只被筛选一次呢?我们只要用它的最小质因子来筛选即可,这便是欧拉筛法。

二,欧拉筛法
欧拉函数求法与欧拉筛法求素数也是非常精妙的算法。
欧拉函数是小于n的正整数中与n互质的数的数目,欧式筛法正是围绕着欧拉函数而展开。
原理:以欧拉函数为本体,衍生操作欧式筛法
欧拉筛法的基本思想 :在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。
先要了解一下特性:
1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a
b]=phi[b]a
3.若a,b互质,phi[a
b]=phi[a]phi[b](当a为质数时,if b mod a!=0 ,phi[ab]=phi[a]phi[b])
代码 :

int n,m[100],phi[100],p[100],nump;
//m[i]标记i是否为素数,0为素数,1不为素数;p是存放素数的数组;nump是当前素数个数;phi[i]为欧拉函数(小于它并与它互质的个数)
int make()
{
        phi[1]=1;//人为规定1不是素数 
    for (int i=2;i<=n;i++)//记录2至n的所有细节 
    {
        if (!m[i])//假如i为素数
        {
            p[++nump]=i;//将i加入素数数组p中
            phi[i]=i-1;//因为i是素数,由特性1得知    
        }    
        for (int j=1;j<=nump&&p[j]*i<n;j++)  //用当前已得到的素数数组p筛,筛去p[j]*i
        {
            m[p[j]*i]=1;//可以确定i*p[j]不是素数 
            if (i%p[j]==0) //看p[j]是否是i的约数,因为素数p[j],等于判断i和p[j]是否互质 
            {
                phi[p[j]*i]=phi[i]*p[j]; //特性2
                break;
            }
            else phi[p[j]*i]=phi[i]*(p[j]-1); //互质,特性3其,p[j]-1就是phi[p[j]]   
        }
    }
}

对于m[p[j]*i]=1 的解释: 这里不是用i的倍数来消去合数,而是把 p里面纪录的素数,升序来当做要消去合数的最小素因子。

参考:https://blog.youkuaiyun.com/qq_39763472/article/details/82428602
https://blog.youkuaiyun.com/qq_41754350/article/details/81609688?tdsourcetag=s_pcqq_aiomsg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值