我的算法学习(2)素数筛之欧拉筛

埃氏筛与欧拉筛的实质都且就是围绕这一句话:素数的倍数不是素数。
假设要筛出n以内的素数。我们先把所有数标记为素数。枚举i从2到n,所以因为i是从小到大的,如果i
没有被前面的数(比它小的数)标记为合数,那i就是素数,加入素数列表。现在用i来筛后面的数,枚举已经筛出来的素数prime[j](j=1~cnt),标记i * prime[j]为合数,当i是prime[j]的倍数时退出循环
欧拉(Euler)筛法是用于找到从1开始,到给定的最大数之间的所有质数的一种筛法,其时间复杂度是O ( n )。
其中欧拉筛法有效地避免了埃拉托斯特尼(Eratosthenes)筛法中重复的筛选,保证了每个数只筛选一次,成功地降低了时间复杂度。


 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define max  100005
bool isprime[max]; //判断i是否为素数
int prime[max]; //已经筛出的素数
int n; //<= n的素数
int cnt = 0; //筛出的素数个数
void pmr()
{
    memset(isprime,true,sizeof(isprime)); //全标记为素数
    isprime[1] = false; //1不是素数
    for(int i = 2;i <= n; ++i)
    {
        if(isprime[i])
        {
            prime[++cnt] = i; //如果i没被前面的数筛掉,则i是素数
        }
        for(int j = 1;j <= cnt&&i * prime[j] <= n; ++j)
        {
            isprime[i * prime[j]] = false; //筛掉i的素数倍,j循环枚举现在已经筛出的素数
            //倍数记为合数
            if(i % prime[j] == 0) 
            {
                //如果i整除了prime[j]退出循环保证时间复杂度。
                break;
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    pmr();
    for(int i = 1;i <= cnt;i++)
    {
        cout<<prime[i]<<endl;
    }
    
}                     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值