质数筛法:朴素素数筛,埃氏筛,欧式筛

简介: 质数筛法:朴素素数筛,埃氏筛,欧式筛

若一个数可以进行因数分解,则得到的两个数一定是有一个>=sqrt(x),另一个<=sqrt(x).

朴素算法

这个算法是最简单的素数判断算法+遍历素组,耗时长


bool judge(ll x)
{   
    if(x==2) return true;
    if(x<2||x%2==0)
        return false;   
    for(int i=3;i<=sqrt(x+1);i+=2)//这个地方可以优化一下,一个是范围,一个是步长 (素数一定是奇数) 
        {
            if(x%i==0)
                return false;
        }
    return true;
}

埃氏筛

利用当前已经找到的素数,从后面的数中筛去当前素数的倍数,当前素数已经是筛去数的质因子,如此下去能筛除之后所有的合数,是一种比较快的筛法

美中不足是会筛除多次比如8和16,同时被2和4筛去


36.png

输入数据

100 2

2

91

输出数据

Yes

No

#include <bits/stdc++.h>
using namespace std;
int prime[10000005];
const int N = 10000000;
void isprime()
{
    fill(prime,prime + N,true);
    prime[1] = false;
    for(int i = 2; i <= N; ++i)
    {
        if(prime[i])
        {
            for(int j = i * 2;j <= N;j += i)
            {
                prime[j] = false;
            }
        }
    }
}
int main()
{
    isprime();
    int n,m;
    cin>>n>>m;
    int num;
    for(int i = 0;i < m;i++)
    {
        cin>>num;
        if(prime[num])
            cout<<"Yes\n";
        else
            cout<<"No\n";
    }
    return 0;
}

欧式筛

这是一种很好的线性筛法,和埃氏筛法的区别是对于每一个要筛除的数,欧拉筛法只筛除一次。原理如下

任何一个合数都可以表示成一个质数和一个数的乘积

假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:

A = x * y; (假设y是质数,x合数)

x = a * b; (假设a是质数,且a < x——>>a<y)

-> A = a b y = a Z (Z = b y)

即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积,那样我们到每一个数,都处理一次,这样处理的次数是很少的,因此可以在线性时间内得到解。

#include <bits/stdc++.h>
using namespace std;
int prime[10000005];
int primesize = 0;
bool isprime[10000005];
void getlist(int listsize)
{
    memset(isprime,1,sizeof(isprime));
    isprime[1] = false;
    for(int i = 2;i <= listsize;i++)
    {
        if(isprime[i])
        {
            prime[++primesize] = i;
        }
        for(int j = 1;j <= primesize && i * prime[j] <= listsize;j++)
        {
            isprime[i * prime[j]] = false;
            if(i%prime[j] == 0)
                break;
        }
    }
}
int main()
{
    int n,m;
    cin>>n>>m;
    getlist(n);
    int num;
    for(int i = 0;i < m;i++)
    {
        cin>>num;
        if(isprime[num])
        {
            cout<<"Yes"<<endl;
        }
        else
        {
            cout<<"No"<<endl;
        }
    }
    return 0;
}
相关文章
|
前端开发
从0搭建Vue3组件库(七):使用 gulp 打包组件库并实现按需加载
从0搭建Vue3组件库(七):使用 gulp 打包组件库并实现按需加载
544 0
|
8月前
|
Linux
Debian下载ISO镜像的方法
步骤 1:访问Debian官方网站 打开你的网络浏览器,在地址栏中输入 https://www.debian.org/ 并回车,这将带你到Debian的官方网站。
1302 6
Debian下载ISO镜像的方法
|
11月前
|
运维 安全 Linux
全面提升系统安全:禁用不必要服务、更新安全补丁、配置防火墙规则的实战指南
全面提升系统安全:禁用不必要服务、更新安全补丁、配置防火墙规则的实战指南
503 12
|
存储 Linux Shell
⭐⭐⭐【Shell 命令集合 磁盘管理 】Linux 挂载文件系统 mount使用教程
⭐⭐⭐【Shell 命令集合 磁盘管理 】Linux 挂载文件系统 mount使用教程
527 0
|
11月前
|
测试技术 开发者 Python
对于Python中的异常要如何处理,raise关键字你真的了解吗?一篇文章带你从头了解
`raise`关键字在Python中用于显式引发异常,允许开发者在检测到错误条件时中断程序流程,并通过异常处理机制(如try-except块)接管控制。`raise`后可跟异常类型、异常对象及错误信息,适用于验证输入、处理错误、自定义异常、重新引发异常及测试等场景。例如,`raise ValueError(&quot;Invalid input&quot;)`用于验证输入数据,若不符合预期则引发异常,确保数据准确并提供清晰错误信息。此外,通过自定义异常类,可以针对特定错误情况提供更具体的信息,增强代码的健壮性和可维护性。
|
自然语言处理 C# 数据安全/隐私保护
50.c#:string类初始化
50.c#:string类初始化
408 1
|
存储 关系型数据库 MySQL
深入理解MySQL:查询表的历史操作记录
深入理解MySQL:查询表的历史操作记录
1418 0
|
算法
数据结构和算法学习记录——时间复杂度的计算(嵌套循环、大O的渐进表示法、双重循环、常数循环、strchr、冒泡排序、二分查找、斐波那契数列递归)
数据结构和算法学习记录——时间复杂度的计算(嵌套循环、大O的渐进表示法、双重循环、常数循环、strchr、冒泡排序、二分查找、斐波那契数列递归)
817 1
|
Java Spring 容器
详解java参数校验之:顺序校验、自定义校验、分组校验(@Validated @GroupSequence)
详解java参数校验之:顺序校验、自定义校验、分组校验(@Validated @GroupSequence)
|
Java
掌握Java 17的利器:Switch语句升级,模式匹配闪耀登场
掌握Java 17的利器:Switch语句升级,模式匹配闪耀登场
244 0