三种素数筛总结——(朴素筛,埃氏筛,线性筛)

2023-10-30

vAHwSP.jpg
但行好事,莫问前程。

题目背景

题目:(leetcode)204.计数质数


给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。

对于这类求解素数个数有关的题目,通常采用质数筛算法。

本文不计算时间复杂度,只介绍自己对于思路的理解。



质数筛

1. 朴素筛法

时间复杂度:

O(n√n)

思想:

对于每一个i∈[2,n],枚举 [2,i-1] 中是否存在 i 的因子,有=》合数,没有=》素数

又因为对于i而言,因子一定是小于√i的,故枚举可以从 [2,i-1] 优化为 [2,√i],因此复杂度为n√n。

代码





2. 埃氏筛法

时间复杂度:

O(n*log(logn))

思想:

在从小到大枚举素数的过程中,设置标志数组val,每找到一个素数便将其倍数全部筛除(因为素数的倍数一定是合数),在后续枚举过程中直接通过判断val跳过合数,剩下来的就是素数。

这里利用了算术基本定理,简而言之就是,所有的合数都可以分解成若干素数的幂的乘积,这里需要思考一下。最新枚举到的合数,其因子一定比其本身要小,那么该因子就一定在之前被枚举到过 <==> 即合数已经在之前被筛除了。

代码:

int IsPrime(int n){
	//计算小于n的素数个数
	int cnt = 0;//计数
	//bool val[5000010]={0};//val[i]表示i是否是素数,先假设全是素数
	bool *val = new bool[5000010]();//val[i]表示i是否是素数,先假设全是素数
	for(int i=2; i<n; i++)
	{
		//标志判断
		if(val[i])//判断i是否是合数
		{
			continue;
		}    
		cnt++;
		//开始筛除(核心算法)
		for(int j=i; j*i<=n; j++){		//开始筛除i的倍数
		//j=i而不是j=2是因为:前面的合数必被过往素数列举了
		//j<=n/i是因为:i*j<=n超出范围了,后者int*int易越界,int/int的形式更加保险。
			val[i*j]=1;
		}
	}
	return cnt;
}



3. 线性筛法

时间复杂度:

O(n)

思路:

线性筛是对于埃氏筛法的优化,举个例子介绍埃氏筛法的缺陷

对于2 3 6这三个数,如果用埃氏筛法,会发现在2筛除过程和3筛除过程中,6都被筛除了一遍,这也就是埃氏筛法的缺陷,会有重复筛除的情况,而线性筛则在用哪个素数进行筛除这个点上作了改进,线性筛采用了若干素数中最小的素数来筛除,基于基本算术定理,我们知道合数都只能被唯一的分解成若干素数的幂的积,因此每个合数只有唯一的最小素因数,这样在筛除过程中就不会发生重筛,因此最终复杂度就变成了O(n)。

代码解释:
具体代码实现较复杂,和埃氏算法不同点在于:
1、多了一个prime数组存储素数
2、从 埃氏筛法:用单个的素数进行筛除 变成 用枚举过程中的 i 对遍历过程中已找到的素数 prime[j] 进行倍乘( i*prime[j] )
3、对 i 进行最小素因子的考察。

代码:

int IsPrime(int n){
	int cnt = 0;//计数
	int prime[5000000];//按顺序依次存储素数
	//bool val[5000010]={0};//val[i]表示i是否是素数,先假设全是素数
	bool *val = new bool[5000010]();//val[i]表示i是否是素数,先假设全是素数
	for(int i=2; i<n; i++)
	{   
        //保存素数
		if(!val[i])//判断i是否是素数
		{
			prime[cnt++] = i;//保存第cnt+1个素数
		}    
        //开始筛除(算法核心)
		for(int j=0; prime[j]<=n/i && j<cnt; j++){		
			val[i*prime[j]] = 1;
            //判断是否prime[j]是否是i的素因数,如果是,则说明后面j++后,prime[j]就不再是i*prime[j]的最小素因数了
            //进行基本算术定理的分解,可以发现此时i*prime[j]=(prime[j-1]^k)*prime[j]
            //上式的最小素因数是prime[j-1],因此直接break该i,进入下一个i。
            if(i % prime[j] == 0)
                break;
		}
	}
	return cnt;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

三种素数筛总结——(朴素筛,埃氏筛,线性筛) 的相关文章

随机推荐

  • Android获取当前位置(GPS和网络定位)

    1 比较 GPS准确度高但耗电多 网络定位耗电少但准确度低 2 代码 添加权限 AndroidManifest xml
  • vue使用百度地图(标点、点击后展示弹框、多个标点、点聚合)

    安装百度地图 npm install vue baidu map save 在百度地图开放平台申请AK 全局注册 在项目的main js中引入 import Vue from vue import baiduMap from vue bai
  • Shell脚本编写教程【五】——Shell 基本运算符

    Shell脚本编写教程 五 Shell 基本运算符 目录 https blog csdn net shn111 article details 131590488 参考教程 https www runoob com linux linux
  • 练习-Java类和对象之包的定义

    第1关 练习 Java类和对象之包的定义 任务描述 编程要求 测试说明 任务描述 本关任务 定义一个电影类和一个电影测试类 在电影测试类中通过对象完成成员变量和成员方法的使用 编程要求 仔细阅读右侧编辑区内给出的代码框架及注释 在 Begi
  • 【Docker】Docker网络

    1 配置容器网络 1 通过实训平台进入到操作系统界面 在 后输入docker run i t d net none ubuntu bin bash命令 启动一个 bin bash容器 示例代码如图1所示 2 在 后输入docker ps a
  • ant-vue中的a-icon使用方法

    Ant Design 图标库 直接引入的使用方式 你直接点击相应的图标会自动将图标名称复制到你的剪切板上
  • Unity3D游戏开发介绍

    Unity3D游戏开发介绍 Unity3D Unity是实时3D互动内容创作和运营平台 包括游戏开发 美术 建筑 汽车设计 影视在内的所有创作者 借助Unity将创意变成现实 Unity平台提供一整套完善的软件解决方案 可用于创作 运营和变
  • CenOS7 下安装wget命令

    1 安装vsfdp yum y install vsftpd 2 关闭防火墙 systemctl stop firewalld service 3 将本机目录下的wget安装文件上传至虚拟机 scp wget 1 14 18 el7 6 1
  • 案例:用户信息列表展示

    1 需求 用户信息的增删改查操作 2 设计 1 技术选型 Servlet JSP MySQL JDBCTempleat Duird BeanUtilS tomcat 2 数据库设计 create database day17 创建数据库 u
  • uva11292 Dragon of Loowater (水题)

    include
  • 电脑怎么在Bios中开启虚拟化

    1 开机按F1进入BIOS Configuration Secuity 2 然后选择Virtulize 或者Intel Virtual Technolody 设置成Enable 3 F10保存 重启
  • String类为什么是不可变的

    String StringBuilder StringBuffer是经常考的东西 其中 String是不可变的 为什么呢 简单解释如下 String类new了一个对象后 我们看到的该对象只是引用 存放了真正内存的地址 并不是真的内存值 如果
  • 500.键盘行 693.交替位二进制数(java实现)

    键盘行 题目 给定一个单词列表 只返回可以使用在键盘同一行的字母打印出来的单词 键盘如下图所示 示例1 输入 Hello Alaska Dad Peace 输出 Alaska Dad 注意 你可以重复使用键盘上同一字符 你可以假设输入的字符
  • 瑞芯微RK3399交叉编译MPP

    上一篇介绍了如何在ubuntu下搭建瑞芯微RK3399的检查编译环境 现在就要开始交叉编译MPP来进行对视频的硬编硬解 这里RK3399用的aarch64架构芯片 上面跑的linux 如果编译android版 需要其他配置 这里主要对lin
  • 101. Symmetric Tree\104. Maximum Depth of Binary Tree\111. Minimum Depth of Binary Tree

    Symmetric Tree 题目描述 代码实现 Maximum Depth of Binary Tree 题目描述 代码实现 Minimum Depth of Binary Tree 题目描述 代码实现 101 Symmetric Tre
  • hcie数通认证考试科目有哪些

    HCIE数通认证考试科目包括网络架构设计和规划 华为路由交换设备的技术和应用 安全和防护 数据中心技术和架构设计以及其他技术和应用1 网络架构设计和规划是HCIE认证考试的重点内容之一 包括网络结构的分层设计 网络拓扑规划 网络性能和可靠性
  • 器件基础知识——电阻

    一 认识电阻 1 耗能能力 电阻对电流有阻碍作用 它自身消耗能量 会将电能转换为热能 为热功率 为流过电阻的电流 为电阻阻值 2 欧姆定律 为加在电阻两端的电压 在电路中为固定值 3 等效模型 理想的电阻器 由纯电阻组成 不受工作频率影响
  • Docker安装教程

    0 安装Docker Docker 分为 CE 和 EE 两大版本 CE 即社区版 免费 支持周期 7 个月 EE 即企业版 强调安全 付费使用 支持周期 24 个月 Docker CE 分为 stable test 和 nightly 三
  • 一个简单的神经网络实例——两层神经网络手写数字识别

    简介 这里是使用神经网络识别手写数字的教程 这个简单的神经网络教程演示了使用numpy从零开始实现一个简单的神经网络 我们定义前向传播和反向传播函数 在训练过程中不断更新权重 完成对数据的拟合 1 准备数据 我们准备了一个简单的训练集 包含
  • 三种素数筛总结——(朴素筛,埃氏筛,线性筛)

    但行好事 莫问前程 题目背景 题目 leetcode 204 计数质数 给定整数 n 返回 所有小于非负整数 n 的质数的数量 对于这类求解素数个数有关的题目 通常采用质数筛算法 本文不计算时间复杂度 只介绍自己对于思路的理解 质数筛 1