简单的素数筛

由于最近学算法学的有点头秃,于是决定来写几篇基础算法的文章,由于本蒟蒻也是新人也是小白,所以尽量会讲一下我当时在学这个算法的时候所产生的一些疑惑,以后来写题的时候出现的一些问题,又鉴于,本人不是学教师教育的www,所以如果那些地方没有讲清楚或者是讲解有问题的话,欢迎各位在这篇文章下面留言,我会看的!那,我们就开始吧,我尽量讲的简单易懂。

第一篇的话我想来写一写关于我又爱又恨以及有着重大发现的素数筛。

当我还不会素数筛的时候,我是怎么来筛质数的呢?很简单,就是按照素数的定义,一点一点的找出来我们所需要的找出来的素数。是放在main函数里面最简单最暴力的一个循环体结构。大概就是像下面这段代码一样吧。

int flag=0;
if(n==0||n==1){
    flag=1;
}for(int i=2;i<n;i++){
    if(n%i==0){
        flag=1;
     }
}if(flag==1){
    printf("no\n")
}else {
    printf("yes\n")
}return 0;

这一段代码就是一个很简单的查找质数,只要有除1和他本身以外的因子,那么他就不是质数,可是这样似乎有点慢,所以,我们可以在这种算法的基础上优化一下。

int flag=0;
if(n==0||n==1){
    flag=1;
}for(int i=2;i<=sqrt(n);i++){
    if(n%i==0){
        flag=1;
     }
}if(flag==1){
    printf("no\n")
}else {
    printf("yes\n")
}return 0;

看出来我在哪里动了手脚吗?没错,我把for循环从1-n的范围改成了从1-sqrt(n),既然是写给新人看的,那我觉得我有必要解释一下,什么叫做sqrt,sqrt是开方函数,就相当于sqrt(1)=1,sqrt(9)=3;这样,这就是开方函数,但是在使用开方函数之前一定要记得加上头文件#include<math.h>或者是#include<cmath>.但是,这种方法的效率太低,会导致TLE或者是RE。所以我们改用了素数筛的方法。

这样的话,也可以加在函数里面用来寻找质数。(U1S1,有些时候用筛法未必有暴力快,万物皆可暴力,而且优化过后的方法,时间复杂度也降下来了好多)

后来,我学了第一个筛法,埃式筛。

int a[N]
void ss(){
    a[1]=1;
    a[0]=1;//这里是因为0.1在不作特殊要求的情况下,都不被看作是质数,除非,题中提到。
    for(int i=2;i<=sqrt(N);i++){
        if(!a[i]){
            for(int j=i*i;j<N;j++){
                a[j]=1;//质数的倍数一定是合数,所以我们把所有的合数都标记了,剩下的都是素数
                        接下来只要判断a[n]就可以找到质数了。
            }
        }
    }
}

埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。

这是一个函数,把它放在代码里,再对数组里的数字进行特判就行,这个就是打表标记的方法,至于我们为什么要使用埃式筛来代替最普通的那种查找,是因为往后写,就会发现不是所有的题目都会让你判断一个数字是不是素数,而是多个,一个两个用那种最普通的方法可能还蛮简单的,但如果是一批一批的数字让我们判断呢?埃式筛的时间复杂度是O(nloglogn)

最后一个,也是效率最高的一个筛法,就是线性筛。也叫做欧拉筛。他的时间复杂度是O(n)但是就我个人而言感觉线性筛是最不好理解的一个。其实这个筛法也是把所有质数的倍数筛掉,并且标记,剩下来的就都是素数了。这个筛法的话,建议尝试一下手动模拟,可能会有出奇的效果。

void isprime(int n){
    for(itn i=2;i<=N;i++){
        if(!num[i]){
            prime[cnt++]=i;
            for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
                num[i*prime[j]]=1;
                if(i%prime[j]==0){
                    break;
                   }
                }
            }
        }
    }
}

最后呢,讲一个最低级最奇怪的筛法吧,之前有人说他又像埃式筛又像欧拉筛,可是大家不知道的是这是一个偷懒写不出标准筛的小孩歪打正着写出来的奇妙筛法。下面就是某小孩偷懒写出来的算法,一度被调侃为鱼氏筛。其实,可能也没有那么拉跨吧wwww...

好啦,有什么不懂的就在评论区评论吧。

int a[N]
void ss()
{
    a[0]=1;
    a[1]=1;
    for(int i=2;i<=N;i++){
        for(int j=2;j*i<=N;j++){
            a[i*j]=1;
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼 kilmo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值