C++筛法求素数

2023-05-16

假定题目为输出n以内的所有素数

一般方法 

最容易理解的一个方法,从0遍历到根号n判断n是否能被整除。使用时只需要记住判断到根号n就可以了。

但是时间复杂度是o(n*sqrt(n)),效率略低。

代码如下:

#include<iostream>
#include<cmath>			//用sqrt()这个函数需要加的头文件 
using namespace std;
int prime(int n)
{
	for(int i=2;i<sqrt(n);i++)		//不需要到n,到根号n就已经足够 
	{
		if(n%i==0)	return 0;		//不是素数返回0,是素数返回1 
	}
	return 1;
}
int main()
{
	int n;
	cin>>n;
	
	for(int i=1;i<=n;i++)
	if(prime(i))	cout<<i<<" ";	//如果是素数就打印在屏幕上 
	
	return 0;
} 

普通筛——埃拉托斯特尼(Eratosthenes)筛法

基本思路:

定义一个长度为maxn的布尔变量数组prime[maxn],数组元素为0则代表所对应的下标为素数,数组元素为1则代表所对应的下标为合数。(下文中2代表prime[2],2的值为prime[2]的值)

我们先把数组里所有元素的值设为1,代表着目前所有小于n的数都被认为是素数。

假设有一个指针,当他指向2时,2的值为1,表示2为素数,程序把2的倍数4,6,8等的值全部设置成0,这代表他们不被认为是素数。

然后那个指针指向3,3的值为1,表示3为素数,程序把3的倍数6,9,12等的值全部设置成0,这代表他们也不被认为是素数。

指针指向了4,4的值已经被指针指向2时设置成了0。它不是素数,没有必要把它的倍数的值也设置成0,因为4能筛掉的合数,2也都能筛掉。

然后就是指针不断的向后移动,找到素数的值,把它们的倍数的值全部设置成0,直到筛到根号n

因为这种算法是层层筛选素数,所以叫筛法求素数。

函数体代码如下:

const int maxn=10000;						//具体的maxn看题目要求 
bool prime[maxn];
void judge_prime(int n)
{
	memset(prime,1,sizeof(prime));			//把prime数组全部初始化为1 
	for(int i=2;i<n;i++)					//for循环可以实现上面所说的指针的功能 
	{
		if(prime[i]==1)						//找到素数 
		for(int j=i*2;j<=n;j+=i)			//把n以及n以内i的倍数的值全部设为0 
		{
			prime[j]=0;
		}
	}	
}

memset(a,b,c)将a这个地址之后c个字节的值全部替换为b

sizeof(a),返回a总共所占的字节数

第一个循环来找素数,第二个循环来枚举那个素数的倍数

上面讲到的这种方法其实有优化的空间,j刚开始不需要设为2i,可以优化为i*i,指针也和基础方法一样,不用指到n,只需要指到根号n(我也不知道为什么,问数学家去)

优化前的时间复杂度有o(nloglogn),优化后就大概接近o(n)了

优化后的总体代码如下:

#include<iostream>
#include<cmath>
#include<string.h>							//包含memset的头文件,也可以写成cstring 
using namespace std;
const int maxn=10000;						//具体的maxn看题目要求 
bool prime[maxn];
void judge_prime(int n)
{
	memset(prime,1,sizeof(prime));			//把prime数组全部初始化为1 
	prime[0]=0;prime[1]=0;					//加上这两句显得更严谨( 
	for(int i=2;i<n;i++)					//for循环可以实现上面所说的指针的功能 
	{
		if(prime[i]==1)						//找到素数 
		for(int j=i*2;j<=n;j+=i)			//把n以及n以内i的倍数的值全部设为0 
		{
			prime[j]=0;
		}
	}	
}
int main()
{
	int n;
	cin>>n;
	judge_prime(n);
	for(int i=0;i<=n;i++)
	{
		if(prime[i])						//如果prime[i]=1,也就是i被认为是素数时,输出i 
		cout<<i<<" ";	
	} 
	return 0;
} 

线性筛——欧拉Euler筛

基本思路:

你有没有注意到,埃氏筛法在指针指向2和3时都把6的值设为了0,重复了,所以会有些浪费,终究不能达到o(n)的时间复杂度。

通过离散数学中的知识,我们可以知道每个合数都能分割成一个素数a和另一个数i(可以是素数)的乘积。

那么欧拉筛要做的,就是要保证每个合数只会被分割后的最小素数a筛掉,避免重复。

先放代码,方便理解:

const int maxn=1e7;
bool prime[maxn+5];
int sto_prime[maxn+5];
void judge_prime(int n)
{
	int cot=0;
	memset(prime,1,sizeof(prime));
	prime[0]=0;prime[1]=0;
	for(int i=2;i<n;i++)							//外层循环指向不同的数i 
	{
		if(prime[i])	sto_prime[cot++]=i;			//保存素数到int数组里 
		for(int j=0;j<cot;j++)						//内层循环指向不同的素数 
		{
			if(i*sto_prime[j]>n)	break;			//如果要筛的那个数超出了最大值,退出内层循环 
			prime[i*sto_prime[j]]=0;				//筛数 
			if(i%sto_prime[j]==0)	break;			//最重要的一句, 保证只每个合数只筛一次 
		}
	}	
}

具体到实现上,我们除了要像上面一样定义一个bool类型的数组,还要定义一个int类型的数组,专门用来存放筛选出来的素数。

还需要两层循环来枚举素数sto_prime和另一个数i。

内层从小到大枚举 sto_prime[j]。i×sto_rime[j] 是尝试筛掉的某个合数,其中,我们期望 sto_rime[j] 是这个合数的最小质因数 (这是线性复杂度的条件,下面叫做“筛条件”)。它是怎么得到保证的?

j 的循环中,有一句就做到了这一点:

if(i%sto_prime[j]==0)	break;

j 循环到 哪里 就恰好需要停止的理由是:

  • 下面用 s(smaller)表示小于 j 的数,l(larger)表示大于 j 的数。

  • ① i 的最小质因数肯定是 sto_prime[j]。

    (如果 i 的最小质因数是 sto_prime[s] ,那么 sto_prime[s] 更早被枚举到(因为我们从小到大枚举质数),当时就要break)

    既然 i 的最小质因数是 sto_prime[j],那么 i × sto_prime[j] 的最小质因数也是 sto_prime[j]。所以,j 本身是符合“筛条件”的。

  • ② i × sto_prime[s] 的最小质因数确实是 sto_prime[s]。

    (如果是它的最小质因数是更小的质数 sto_prime[s],那么当然 sto_prime[s] 更早被枚举到,当时就要break)

    这说明到 j 之前(用 i × sto_prime[s] 的方式去筛合数,使用的是最小质因数)都符合“筛条件”。

  • ③ i × sto_prime[l] 的最小质因数一定是 sto_prime[l]。

    (因为 i 的最小质因数是 sto_prime[j],所以 i × sto_prime[l]也含有 sto_prime[j] 这个因数(这是因为),所以其最小质因数也是 sto_prime[j](新的质因数 sto_prime[l] 太大了))

    这说明,如果 j 继续递增(将以 i × sto_prime[l] 的方式去筛合数,没有使用最小质因数),是不符合“筛条件”的。

欧拉筛因为每个数都只被筛一次,复杂度只有o(n),是最好的筛选素数的方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++筛法求素数 的相关文章

  • 安装paramiko报错:Requirement already satisfied (use --upgrade to upgrade): paramiko in /usr/local/lib/py

    开始将 upgrade 位置写到了pip3后面 xff0c 报错 xff0c 浪费很多时间去找各种解决办法 xff0c 只能说对pip3语法结构不熟悉
  • fgets和gets的区别

    在编程中发现gets 和 fgets 一些区别总结一下 xff1b 1 fgets比 gets 安全 xff0c 使用 gets 编译时会警告 为了安全 xff0c gets 少用 xff0c 因为其没有指定输入字符的大小 xff0c 限制
  • java.lang.IllegalStateException android.media.MediaPlayer._prepare(Native Method)

    目录 错误log xff1a 原因 xff1a 错误log xff1a 1566550586 419 28478 28478 com stone stonemusic W System err java lang IllegalStateE
  • Android自定义view刷新方法

    目录 描述 描述 Android view的刷新有三个方式 xff1a span class token comment 只会触发执行onDraw方法 xff0c 只会改变绘制里面的内容 条目的绘制 span span class toke
  • Ubuntu升级后VMware缺少vmmon、vnnet

    Ubuntu升级系统后启动时 xff0c 缺少vmmon vnnet 解决方式运行以下脚本 xff0c 可以修改 span class token shebang important bin bash span VMWARE VERSION
  • XMMS乱码的解决办法

    一 X org 下 XMMS aMule 等 Gtk1 程序的中文解决 这样做以后如果还不行 那么 二 1 安装 xmms mpg123 ja 代码 sudo apt get install xmms mpg123 ja xmms mpg1
  • ConnectionRefusedError: [Errno 111] 拒绝连接

    pip3 install upgrade pip 结果 Exception Traceback most recent call last File 34 usr share python wheels urllib3 1 19 1 py2
  • 设计模式-多例模式

    参考 xff1a 设计模式之禅 目录 多例模式类图实现1 皇帝2 大臣 运行结果补充 多例模式 这种情况有没有 有 大点声 有没有 有 是 确实有 就出现在明朝 那三国期间的算不算 不算 各自称帝 各有各的地盘 国号不同 大家还记得那首诗
  • python3-socket-Demo

    python3 socket Demo 1 背景2 Demo实现2 1 查看端口2 2 服务端2 3 客户端 1 背景 想了解一下python socket编程 xff0c 学习一下 34 白月黑羽 34 的Demo xff0c 做一下记录
  • 【数据库-MySQL-从入门到精通】【学习笔记】

    数据库 01 1 MySQL安装1 1 官网下载1 2 安装1 2 1 安装失败解决方案 xff1a 2 MySQL初学2 1 数据库基础 命令行形式2 2 MySQL操作数据库和数据表2 3 MySQL数据表基本数据类型 鸣谢 xff1a
  • Android7~8.1源码编译失败(Communication error with Jack server (35), try ‘jack-diagnose‘ or see Jack serve)

    目录 1 背景1 1 报错信息 2 原因2 1 分析 3 解决方案3 1 杀掉服务3 2 修改JDK配置文件 xff0c 移除可能导致端口占用的配置3 3 重启服务 1 背景 Android7 0 8 1编译过程中可能会出现异常报错 xff
  • android mediaplay 出现IllegalStateException的几种可能性及解决办法

    1 错误log java lang IllegalStateException at android media MediaPlayer setDataSource Native Method at android media MediaP
  • 创建.xml的矢量图片;使用Android studio 和 SVG图 生成.xml矢量图标

    Android开发中 xff0c 为什么要使用矢量图标 xff1f 使用矢量图标有什么好处 xff1f 如果使用 png xff1b jpg 这样的图片 xff0c 一般在资源文件中 xff0c 都需要准备不同分辨率的图 这样既让apk臃肿
  • 设计模式-单例模式

    本文章参考慕课DocMike老师的讲解 xff0c 作为个人笔记 xff0c 也希望能帮到需要的人 1 单例模式 单例模式 xff08 Singleton Pattern xff09 是 Java 中最简单的设计模式之一 这种类型的设计模式
  • Android studio 3 gradle配置问题

    目录 问题描述原因解决方法1 xff09 使用低版本的三方依赖库2 xff09 手动声明 xff0c 排除高版本的依赖参考文章 问题描述 Duplicate class android support design widget Coord
  • 51单片机定时器中断按键消抖(无延时)

    单片机入门学习记录 xff08 二 xff09 在机械按键的触点闭合和断开时 xff0c 都会产生抖动 xff0c 为了保证系统能正确识别按键的开关 xff0c 就必须对按键的抖动进行处理 按键的抖动对于人类来说是感觉不到的 xff0c 但
  • Ubuntu常用命令

    目录 更新仓库命令查看软件依赖包安装软件定时查看某个命令查找文件查找文件中的内容 grep 将命令行中输出内容保存文档scp通过ssh连接复制文件修改环境变量删除指定路径下包含某个关键字的文件与文件夹压缩解压查看运行信息远程桌面连接Wind
  • C#: WMI 获取远程 Windows 主机信息

    起步文档 xff1a WMI 基本介绍 WMI调用基本步骤 一个简单的远程访问例子 xff1a xff08 参考自MSDN How To Connect to a Remote Computer xff09 span class hljs
  • 端到端是什么意思?

    不久前 xff0c 燕姐 表扬了我 原话是 xff1a 像你这样端到端负责的人现在越来越少了 哈哈 xff0c 听到这话 xff0c 还是有点高兴的 xff0c 今天我来闲扯一下端到端 客户需要一个求立方差的系统 假设是fun系统 xff1
  • 电磁波和声波对比实验

    如图 xff0c 电话拨通 xff0c 能听到两个手机的声音 不断对右边的罩子进行抽气 xff0c 右边手机的声音越来越小 抽成真空的时候 xff0c 右边手机的声音消失 xff0c 但左边手机仍然如初 此时 xff0c 右边手机发送的信号

随机推荐

  • eclipse用MVC模式编写简单的JSP登录界面(一)

    刚开始接触JSP xff0c 打算写写博客记录记录 xff0c 大佬可以不用看了 1 JSP 在编写登录界面之前需要安装服务器 xff08 这里使用的是Tomcat xff09 并且安装IDE以及进行相关的部署 这里就不进行赘述了 xff0
  • seata

    Seata 1 seata概述 1 1 Seata简介 Seata 是一款开源的分布式事务解决方案 xff0c 致力于提供高性能和简单易用的分布式事务服务 Seata 将为用户提供了 AT TCC SAGA 和 XA 事务模式 xff0c
  • git clone出现fatal: HTTP request failed --git版本问题

    当git版本低于2 0版本时 xff0c 在push或clone代码时容易出现 fatal HTTP request failed 的问题 当前 xff0c git的最新版本是2 33 1 但是 xff0c 当我按官网提示 xff0c 用
  • 层次狄利克雷过程HDP(Hierarchical Dirichlet Processes)

    HDP本质是一个聚类算法 xff0c 自动决定聚类的个数 HDP HMM也是一个聚类算法 xff0c 自动决定HMM的隐状态的个数 xff0c 以每个隐状态作为一个聚类 LDA是主题模型 xff0c 可以被用作聚类算法 HDP也是个主题模型
  • vscode离线安装插件方法

    在实际工作中 xff0c 由于大多开发环境为内网开发 xff0c 无法连接外网 xff0c 需要进行离线安装相应插件 xff0c 此文用于记录vscode离线安装插件方法 1 方法一 xff1a 到vscode官网 https market
  • AD--------简单规则的设定

    这学期打了好多块板子 xff0c 都是在大佬的帮助下弄得 xff0c 嘿嘿嘿 xff0c 以后得多多练习 AD的规则设定 xff0c 反正对于英文不好的我来说还是比较难得 xff0c 但是现在画的板子规则设定都比较简单 rules 最小间距
  • linux系统编程中的信号量--模拟生产者与消费者

    FileName producer and customer c description This app demonstrates how to use the semaphore solve the problem about the
  • MySQL数据库索引相关知识

    目录 定义重点 存储原理B TreeB 43 TreeMyISAMInnoDB主键使用自增整形主键联合索引 原则那些情况应当创建索引不适合见索引 定义 索引时帮助MySQL高效获取数据的数据结构 简单说 xff1a 排好序的快速查找数据结构
  • 解决Mac M1环境下使用Goland debug失败的问题

    问题描述 xff1a 在m1环境下 xff0c 使用GoLand工具 xff0c 项目可以正常Run xff0c 但无法Debug运行 error could not launch process can not run under Ros
  • 解决“java.sql.SQLException: Expression #1 of ORDER BY clause is not in SELECT list,references column”

    在一次跑项目的时候 xff0c 报了这个错 分析原因 xff1a 百度发现是Mysql5 7及以上版本默认将 sql mode 的 ONLY FULL GROUP BY 模式设置为打开状态 解决办法 xff1a 1 将数据库换回5 6及以下
  • Lottie动画使用及原理分析

    1 Lottie是什么 xff1f Lottie是Airbnb开源的一个动画渲染库 xff0c 支持多平台 xff0c 包括iOS Android React Native以及Flutter xff08 https github com a
  • Windows Vista 下载

    Windows Vista 下载 简介 xff1a 2005年7月22日 xff0c 微软宣布 Windows Vista 为这款新操作系统的名字 微软于2006 年11月2日完成GA版本 xff0c 向OEM和企业用户发布 2007年1月
  • ubuntu 安装VS 转

    以下文字转 在ubuntu 安装VS 人生不过一闭一睁的博客 CSDN博客 ubuntu安装vs2017 able of Contents 一 前言 二 安装过程 1 下载VS Code 2 安装过程 3 下载C 43 43 模块 4 汉化
  • SQL2000 好书 《SQL Server 2000数据库管理与开发技术大全》----求是科技 人民邮电出版社

    SQL2000 好书 SQL Server 2000数据库管理与开发技术大全 求是科技 人民邮电出版社
  • 小米 pro 笔记本拆机-加固态

    前言 小米 pro 笔记本 256G 的固态 xff0c 有点不够用 xff0c 因此想加装固态 网上一打听 xff0c 拆机加固态售后要 100 元人民币 这哪行呀 不能这么便宜小米了 xff0c 100块我都不给你 xff01 准备工作
  • android四大组件之Activity - (2)onNewIntent()的作用

    要说onNewIntent 就不得不提到Activity的四种启动模式 分别是 1 standard 标准模式 也是系统默认的模式 每次都会新建Activity放置任务栈中 2 singleTop 模式 这个模式能够确保每次使用的Activ
  • 解决谷歌无法加载扩展程序

    方法一 1 先将下载的文件 crx格式修改为 zip 2 然后解压zip格式文件 3 选择加载解压过的zip文件 即可 方法二 1 在Google Chrome浏览器的桌面快捷方式上鼠标右键 xff0c 选择属性 R xff0c 进入如下界
  • 好玩的CMD几个命令

    1 msg命令 如果是在局域网中使用msg命令可以达到恶作剧的效果 msg server 192 168 1 26 东东是个人物 xff01 server 这里输入要发送人的IP地址 后面是输出的文字 2 Nslookup 检查网站的ip地
  • MySQL数据库使用相关语句

    目录 MySQL数据库的安装位置创建命令建库查看插入 编码格式配置文件修改数据库外网权限索引 MySQL数据库的安装位置 etc my cnf mysql配置文件 usr bin 客户端程序和脚本 usr sbin mysqld 服务器 v
  • C++筛法求素数

    假定题目为输出n以内的所有素数 一般方法 最容易理解的一个方法 xff0c 从0遍历到根号n判断n是否能被整除 使用时只需要记住判断到根号n就可以了 但是时间复杂度是o xff08 n sqrt xff08 n xff09 xff09 xf