【数学】素数的判断(普通法+埃氏筛法)

文章介绍了素数的概念,从暴力遍历的O(n)算法到优化后的O(sqrt(n))算法,以及更高效的埃氏筛法来寻找素数。通过示例代码展示了如何用C++实现这些算法,并讨论了不同方法的时间复杂度。最后提出了一道找出1-n内素数数量的习题,该题目的解决方案具有O(nloglogn)的时间复杂度。
摘要由CSDN通过智能技术生成

一.素数的概念

素数是指只能被1和自身整除的正整数。换句话说,如果一个数除了1和它本身以外没有其他因数,那么它就是素数。例如,2、3、5、7、11、13等都是素数,而4、6、8、9、10等就不是素数。素数在数学和计算机科学中都有广泛的应用。

01既不是素数也不是合数!

二.根据概念写出的暴力算法(O(n))

思路:既然只能被1和本身整除的是素数,那不妨枚举(1,n)直接的数,若能整除,则不是素数!

代码:

#include<bits/stdc++.h> // 引入头文件,包含了所有标准库函数的声明
using namespace std; // 使用标准命名空间

bool is_prime(int n){ // 定义一个函数,判断一个数是否为素数
    for(int i=2;i<n;i++){ // 从2开始遍历到n-1
        if(n%i==0) return false; // 如果n能被i整除,说明n不是素数,返回false
    }
    return true; // 如果n不能被任何一个i整除,说明n是素数,返回true
}

int main(){ // 主函数
    int n; // 定义一个整型变量n
    cin>>n; // 从标准输入读入一个整数n
    if(is_prime(n)) cout<<"Yes"<<endl; // 如果n是素数,输出Yes
    else cout<<"No"<<endl; // 如果n不是素数,输出No
    return 0; // 返回0,表示程序正常结束
}

三.优化O(sqrt(n))

聪明的我们不难发现,当我们查找11是否为素数时,实则经历了以下比较:

11%2,11%3,11%4,11%5,11%6,11%7,11%8,11%9,11%10;

如果还不能发现问题的话,可以这样看,例如n=10时,要经历10%2,又要经历10%5,岂不浪费了吗?

其实我们只需要检查到\sqrt[]{n}即可。后面再检验就重复了。

#include<bits/stdc++.h> // 引入头文件,包含了所有标准库函数的声明
using namespace std; // 使用标准命名空间

bool is_prime(int n){ // 定义一个函数,判断一个数是否为素数
    for(int i=2;i*i<n;i++){ // 从2开始遍历到sqrt(n)
        if(n%i==0) return false; // 如果n能被i整除,说明n不是素数,返回false
    }
    return true; // 如果n不能被任何一个i整除,说明n是素数,返回true
}

int main(){ // 主函数
    int n; // 定义一个整型变量n
    cin>>n; // 从标准输入读入一个整数n
    if(is_prime(n)) cout<<"Yes"<<endl; // 如果n是素数,输出Yes
    else cout<<"No"<<endl; // 如果n不是素数,输出No
    return 0; // 返回0,表示程序正常结束
}

四.埃氏筛法

若我们要找1-10000中的素数呢?那这样做的话就算是优化后的找素数,时间复杂度也太大了。

这时我们需要一个新的思路,没错,就是埃氏筛法。


 埃氏筛法(Sieve of Eratosthenes)是一种用于找出一定范围内所有素数的算法。它的基本思想是从2开始,将每个素数的倍数都标记成合数,直到筛子无法再筛下去为止。最终留下的就是素数。

其实也就是先开个bool数组,从2开始找出所有倍数,将其标记为true,然后找下一个没被标记的数,继续重复以上操作,直到枚举到^{\sqrt{n}}.


动图演示:

 图来源与:(14条消息) 埃拉托色尼筛选法巧解质数问题(埃氏筛法求解素数问题)_质数筛选法动图_吴雨4的博客-CSDN博客

 五.习题:

找出1-n有多少素数(n<100000)

这个程序的时间复杂度为O(nloglogn),可以处理更大的范围内的素数。

#include<bits/stdc++.h>
using namespace std;

const int MAX=100000; // 边界,具体取决于题目,本题为:n<100000;
bool prime[MAX]; // 默认false为素数。

void sieve(int n){
    prime[1]=true; // 1不是素数
    for(int i=2;i*i<=n;i++){ // 从2开始遍历到sqrt(n)
        if(!prime[i]){ // 如果i是素数
            for(int j=i*i;j<=n;j+=i){ // 将i的倍数标记成合数
                prime[j]=true;
            }
        }
    }
} 

int main(){
    int n;
    cin>>n;
    sieve(n); // 筛出n以内的素数
    int ans=0; // 计数器,记录素数个数
    for(int i=2;i<=n;i++){ // 遍历1-n之间的所有数
        if(!prime[i]) ans++; // 如果i是素数,计数器加1
    }
    cout<<ans<<endl; // 输出素数个数
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值