【算法每日一练]-数论(保姆级教程 篇1 埃氏筛,欧拉筛)

目录

保证给你讲透讲懂

第一种:埃氏筛法

第二种:欧拉筛法

 题目:质数率

题目:不喜欢的数

思路:


        

        

        
问题:1~n 中筛选出所有素数(质数)

有两种经典的时间复杂度较低的筛法,即埃氏筛法和欧拉筛法。

既然是筛子,那么核心思想就是:根据当前的数筛掉后面的一些不合法数据,留下的每个数都是质数。    

第一种:埃氏筛法

(也是最好理解的筛子,不过速度O(n*loglogn))

        

首先2是最小的素数,将表中所有的2的倍数划去。

表中剩下的最小的数字就是3,所以3是素数。再将表中所有的3的倍数划去……

以此类推,如果表中剩余的最小的数是几,几就是素数。然后将其倍数筛掉

核心代码: 

第二个for为什么从i*i开始:

答:我们会先筛2的所有倍数,然后是3的倍数,但是后面在筛3的倍数的时候我们还需要从2开始筛吗?筛掉3*2?这个之前在筛2的时候就已经标记过了的,那么直接从3本身筛开始多好啊。

int eprime(int n){
	judge[0]=judge[1]=1;
	for(int i=2;i<=n;i++){
		if(judge[i]==0){
			prime[cnt++]=i;
			for(int j=i*i;j<=n;j+=i) judge[j]=1;//直接从i本身开始筛
		}
	}
	return cnt;
}

重点: 虽然埃氏筛易理解,但是个别时候还是会被卡的。

我们深入理解埃氏筛的思想:

要想得到 n以内的质数,就要把不大于根号n的质数的倍数全部剔除,剩下的就是质数。从 2 开始,把 2 的倍数(不包括本身)标记为合数,然后向后枚举,查到一个未标记为合数的,就把它的倍数(不包括本身)标记为合数。以此类推,查到 n 为止。
例如一个数 24,它会被 2 标记一次,被3标记一次。如果这个数的质因数较多,那么重复的就会更多,每个已经被筛掉的数重复的被筛,这就会导致时间变长

        (放心,欧拉来了) 

第二种:欧拉筛法

欧拉筛法的原理同埃氏筛法,只不过多了一个判断删除与标记最小质因子的过程。

在埃氏筛法中,一个合数来说可能会被筛多次,比如6可以被2筛去,也可以被3筛去,而欧拉筛要做的事情就是让一个合数只被筛一次。

我们规定这个合数只会被它的最小质因数筛掉。这样能保证每个合数只会被筛一次。

核心代码 

int oprime(int n){//线性筛O(n)速度求出小于n的所有质数!!!
	judge[0]=judge[1]=1;
	for(int i=2;i<=n;i++){
		if(!judge[i]) prime[cnt++]=i;//没有被标记过的数必然是质数,加入质数中
		for(int j=0;prime[j]*i<=n;j++){//质数性倍增(只枚举当然已放入的质数)
			judge[prime[j]*i]=true;//此数的质数倍数加入标记中
			if(i%prime[j]==0)break;//保证了一个合数只被它最小的质因子枚举标记,而一个质数只会一直枚举标记到本身
		}
	}
	return cnt;
}

过程如下:

从 2开始:2 加入 prime 数组,从小到大枚举质数(现在只有 2),筛掉质数与 2 的乘积(4 被筛掉)。
到了 3:   3 加入 prime 数组,从小到大枚举质数(此时有 2,3),筛掉质数与 3 的乘积(6,9 被筛掉)。

到了 4:   4 没加入 prime 数组,枚举质数(有2,3),筛掉 8 后,因为 4mod2=0,触发退出条件。(不触发,就会筛掉 12,而 12=2×2×3,又会被 2 和 6筛一次,懂了吗)
以此类推,可做出一张表:

不难发现保证一个合数只被它最小的质因子枚举标记,而一个质数只会一直枚举标记到本身。保证了合数只被一次筛掉。

下面是完整代码:

#include <bits/stdc++.h>//线性筛模板
using namespace std;
bool judge[1000000];
int n,cnt,prime[1000];
int oprime(int n){//线性筛O(n)速度求出小于n的所有质数!!!
	judge[0]=judge[1]=1;
	for(int i=2;i<=n;i++){
		if(!judge[i]) prime[cnt++]=i;//没有被标记过的数加入质数中
		for(int j=0;prime[j]*i<=n;j++){//1,质数性倍增(只枚举当然已放入的质数)
			judge[prime[j]*i]=true;//此数的质数倍数加入标记中(必然不是质数)
			if(i%prime[j]==0)break;//2,保证一个合数只被它最小的质因子枚举标记,而一个质数只会一直枚举标记到本身
		}
	}
	return cnt;
}
int eprime(int n){
	judge[0]=judge[1]=1;
	for(int i=2;i<=n;i++){
		if(judge[i]==0){
			prime[cnt++]=i;
			for(int j=i*i;j<=n;j+=i) judge[j]=1;
		}
	}
	return cnt;
}
int main(){
	cin>>n;eprime(n);
	//oprime(n);
	for(int i=0;i<cnt;i++){
		cout<<prime[i]<<' ';
	}
	return 0;
}

以上算法只有两步(已标出)和埃氏筛不同,注意一下即可 

最终效果:zhi数组里面全是质数,vis数组里面为true的都不是质数,既方便取质数,又方便判断质数。

        

        下面是练习题

 题目:质数率

题意:求1~n的质数占比(n<=1e8)

(这道题还是很友好的,直接让你精确,而不是求逆元,哈哈哈哈哈)

#include <bits/stdc++.h>
using namespace std;
const int N=1e8+7;
int zhi[N],cnt,m;
bool vis[N];//千万不要用int来充当bool了,内存直接超256M了!!!
int getzhi(int n){
	for(int i=2;i<=n;i++){
		if(!vis[i])zhi[cnt++]=i;    //如果你这里想用++cnt,那么后面的j应该从1开始
		for(int j=0;zhi[j]*i<=n;j++){
			vis[zhi[j]*i]=true;
			if(i%zhi[j]==0)break;
		}
	}
	return cnt;
}
int main(){
	cin>>m;
	getzhi(m);
	printf("%0.3lf\n",(double)cnt/m);
}

      

      

题目:不喜欢的数

我们不喜欢7的倍数;数字的某一位是7,这个数字的倍数我们也不喜欢。给t个数,如果这个数不是喜欢的数就输出下一个喜欢的数

     

思路:

  
注意到一个含7的数的倍数也不行,很明显我们倒着找的话需要找所有的因数来判断,但是t太大了,这样必然超时。只能正着来做!

     
线性筛思想O(n):如果此数喜欢,那就加入数组;否则就把此数的倍数全部筛掉

     
注意到要输出不喜欢数的下一个喜欢的数。

对于这种取一个数的后一个数,那就定义一个链表呗(就是跟踪数组嘛)里面存放下标可以,直接存放那个数也可以,感觉你直接存那个数的话更好!
    

        

#include <bits/stdc++.h>
using namespace std;//如果是喜欢的数,就输出下一个喜欢的数(大于次数的下一个喜欢的数)(t<=2e5    x<=1e7)
const int N=1e7+7;
int t,x,ans[N],nxt[N],cnt;
bool judge[N]={1};
bool check(int x){
	while(x){
		if(x%10==7)return true;
		x/=10;
	}
	return false;
}
void getnum(int n){//线性筛思想
	int cur=1;//cur是上个喜欢的数,此时是第一个喜欢的数
	for(int i=2;i<=n;i++){
		if(!judge[i]){//忽略被筛掉的数
			bool f=check(i);
			if(!f){//喜欢
				ans[cnt++]=i;//放入数组,感觉此步骤有点多余
				nxt[cur]=i;//更新链表,里面存入这个数的下个数
				cur=i;//更新cur
			}else{
				for(int j=i;j<=n;j+=i)//线性倍增的结果都标记一下(都是不喜欢的数)
					judge[j]=true;
			}
		}
	}
}
int main(){
	getnum(N);//先对所有范围内的数都打下表格
	cin>>t;
	while(t--){
		cin>>x;
		if(judge[x]) cout<<-1<<'\n';//不喜欢则直接输出-1
		else cout<<nxt[x]<<'\n';//喜欢则输出这个数的下一个数
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/516405.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

靶向载药脂质体纳米药物载体应用领域

【中文名称】 载药脂质体 【纯 度】 95%以上 【保 存】 4℃保存 【溶 剂】 PBS或者水 【无菌处理】 是 【规 格】 50mg&#xff0c;10mg/ml 【品 牌】 碳水科技&#xff08;Tanshtech&#xff09; 载药脂质体是一种利用脂质双层囊泡包裹药物分子以实现有效…

计算机网络:数据链路层 - 可靠传输协议

计算机网络&#xff1a;数据链路层 - 可靠传输协议 可靠传输概念停止-等待协议 SW回退N帧协议 GBN选择重传协议 SR 可靠传输概念 如下所示&#xff0c;帧在传输过程中受到干扰&#xff0c;产生了误码。接收方的数据链路层&#xff0c;通过真伪中的真检验序列 FCS 字段的值&…

【Linux】-进程知识铺垫①计算机硬件的组织:冯诺依曼体系结构详细解读②关于操作系统对软硬件及用户的意义

目录 ​编辑 1.关于计算机的体系结构 1.1 冯诺依曼体系结构的诞生 2.冯诺依曼体系结构 2.1 cpu:运算器&#xff1a;更多的是让cpu具有特殊的数据计算功能&#xff1a; 2.2 控制器 2.3输入设备 2.4输出设备 3.计算机各个硬件设备之间的关系 4.内存与计算机效率 5.关于为什么总说…

Spoon Taking Problem(c++题解)

题目描述 &#xfffd;N 人が円卓に座っており&#xff0c;各人は反時計回りに順に 1, …, &#xfffd;1, …, N と番号付けられています&#xff0e;各人はそれぞれ左右どちらか一方の利き手を持っています&#xff0e; 円卓上には 1, …, &#xfffd;1, …, N と番号付け…

【Linux】详解动态库链接和加载对可执行程序底层的理解

一、动静态库链接的几种情况 如果我们同时提供动态库和静态库&#xff0c;gcc默认使用的是动态库。如果我们非要使用静态库&#xff0c;要加-static选项。如果我们只提供静态库&#xff0c;那可执行程序没办法&#xff0c;只能对该库进行静态链接&#xff0c;但程序不一定整体…

为移动云数据实现基于可撤销属性组的加密:多代理辅助方法

参考文献为2023年发表的Achieving Revocable Attribute Group-Based Encryption for Mobile Cloud Data: A Multi-Proxy Assisted Approach 动机 对于目前的代理辅助的可撤销基于属性加密来说&#xff0c;外包解密存一些缺点。当多个具有相同属性的用户请求外包转换时&#x…

核心API-Activiti7从入门到专家(3)

背景 今天的说的api&#xff0c;activiti7真有&#xff0c;但真不是这个&#xff1a; 这个是为了云服务&#xff0c;封装的一些api&#xff0c;以后我们还会逐步探讨&#xff0c;今天我们讨论的&#xff0c;是其真正的api&#xff0c;以前是这样的&#xff1a; 是的&#xff0…

ChatGPT 登陆报错:“Oops, an error occurred!” 如何解决?

ChatGPT登录时报错&#xff1a;“Oops, an error occurred!” 说明&#xff1a;哎呀&#xff0c;出错了! 原因&#xff1a; 目前出现这个情况的小伙伴&#xff0c;并非账号被封&#xff0c;多是服务端的问题&#xff0c;比如高峰段&#xff0c;服务端响应不及时&#xff0c;负…

[Apple Vision Pro]开源项目 Beautiful Things App Template

1. 技术框架概述&#xff1a; - Beautiful Things App Template是一个为visionOS设计的免费开源软件&#xff08;FOSS&#xff09;&#xff0c;用于展示3D模型画廊。 2. 定位&#xff1a; - 该模板作为Beautiful Things网站的延伸&#xff0c;旨在为Apple Vision Pro用户…

leetcode代码记录(打家劫舍 III

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为 root 。 除了 root 之外&#xff0c;每栋房子有且只有一个“父“房子与之相连。一番侦察之后&#xf…

【数据结构】——二叉树的递归实现,看完不再害怕递归

创作不易&#xff0c;感谢三连加支持&#xff1f;&#xff01; 一 递归理解 递归无非就是相信它&#xff0c;只有你相信它&#xff0c;你才能写好递归&#xff01;为什么&#xff1f;请往下看 在进入二叉树的实现之前&#xff0c;我们得先理解一遍递归&#xff0c;可能很多…

通用开发技能系列:Authentication、OAuth、JWT 认证策略

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 通用开发技能系列 文章&#xff0c;主要对编程通用技能 Authentication、OAuth、JWT 认证策略 进行学习 1.Basic Authentication认证 每个请求都需要将 用户名密码 进行base64编码后&#xff0c;放在请求头的A…

网络基础二——TCP可靠性实现机制补充

11.3.4确认应答机制 ​ 1.双方通信时要返回确认应答报文&#xff0c;保证对方发送的报文是有效的&#xff1b;尽管整个通信过程中无法保证数据全部可靠&#xff0c;但是可以保证单个方向发送的数据是可靠的&#xff1b; ​ 发送的报文要设置序号&#xff0c;如果是应答报文要…

腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践

腾讯云容器与Serverless的融合&#xff1a;探索《2023技术实践精选集》中的创新实践 文章目录 腾讯云容器与Serverless的融合&#xff1a;探索《2023技术实践精选集》中的创新实践引言《2023腾讯云容器和函数计算技术实践精选集》整体评价特色亮点分析Serverless与Kubernetes的…

基于springboot实现校园资料分享平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现校园资料分享平台演示 摘要 随着信息互联网购物的飞速发展&#xff0c;国内放开了自媒体的政策&#xff0c;一般企业都开始开发属于自己内容分发平台的网站。本文介绍了校园资料分享平台的开发全过程。通过分析企业对于校园资料分享平台的需求&#xff0c;创…

设计模式总结-面向对象设计原则

面向对象设计原则 面向对象设计原则简介单一职责原则单一职责原则定义单一职责原则分析单一职责原则实例 开闭原则开闭原则定义开闭原则分析开闭原则实例 里氏代换原则里氏代换原则定义里氏代换原则分析 依赖倒转原则依赖倒转原则定义依赖倒转原则分析依赖倒转原则实例 接口隔离…

React 入门

一、官网地址 英文官网: https://reactjs.org/中文官网: https://react.docschina.org/ 二、React 特点 声明式编码组件化编码React Native 编写原生应用高效&#xff08;优秀的 Diffing 算法&#xff09;高效的原因&#xff1a;1.使用虚拟DOM&#xff0c;不总是直接操作页面…

Navicat Premium 16 Mac/win---数据库设计、管理与维护轻松掌握数据库管理精髓

Navicat Premium是一款功能强大的数据库开发工具&#xff0c;支持多种数据库系统&#xff0c;如MySQL、Redis、MariaDB、Oracle等&#xff0c;并可与云数据库兼容&#xff0c;如Amazon RDS、Microsoft Azure等。它提供了直观易用的用户界面&#xff0c;使得开发者能够轻松上手并…

递归算法讲解2

前情提要 上一篇递归算法讲解在这里 递归算法讲解&#xff08;结合内存图&#xff09; 没看过的小伙伴可以进去瞅一眼&#xff0c;谢谢&#xff01; 递归算法的重要性 递归算法是非常重要的&#xff0c;如果想要进大厂&#xff0c;以递归算法为基础的动态规划是必考的&…

基于单片机的无线红外报警系统

**单片机设计介绍&#xff0c;基于单片机的无线红外报警系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的无线红外报警系统是一种结合了单片机控制技术和无线红外传感技术的安防系统。该系统通过无线红外传感器实…