【算法每日一练]-数论(保姆级教程 篇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';//不喜欢则直接输出-1else cout<<nxt[x]<<'\n';//喜欢则输出这个数的下一个数}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯真题:路径

import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {int n 2022; //从下标为1开始&#xff0c;方便计算int[] q new int[n]; //存储最短路q[1] 0; //起始条件for (int i 2; i < 202…

C语言 | Leetcode C语言题解之3题无重复字符的最长子串

题目&#xff1a; 题解&#xff1a; int lengthOfLongestSubstring(char * s) {//类似于hash的思想//滑动窗口维护int left 0;int right 0;int max 0;int i,j;int len strlen(s);int haveSameChar 0;for(i 0; i < len ; i ){if(left < right){ //检测是否出现重…

5.2 通用代码,数组求和,拷贝数组,si配合di翻转数组

5.2 通用代码&#xff0c;数组求和&#xff0c;拷贝数组&#xff0c;si配合di翻转数组 1. 通用代码 通用代码类似于一个用汇编语言写程序的一个框架&#xff0c;也类似于c语言的头文件编写 assume cs:code,ds:data,ss:stack data segmentdata endsstack segmentstack endsco…

谷歌浏览器必用AI插件 - elmo,好用,还免费

功能&#xff1a; 1、即时生成网站内容摘要&#xff1b; 2、支持提问并从页面获得直接回答&#xff1b; 3、通过关键词获取相关信息&#xff1b; 4、可以与 PDF 对话&#xff0c;方便理解大型文档、学习或审阅报告&#xff1b; 5、与 YouTube 视频交互问答&#xff08;测试…

探索前端架构:MVC、MVVM和MVP模式

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

sky06笔记下

1.边沿检测 检测输入信号din的上升沿&#xff0c;并输出pulse module edge_check ( clk, rstn, din, pulse ); input wire clk,rstn; input wire din; output reg pulse;wire din_dly;always (posedge clk or negedge rstn)beginif(!rstn)din_dly < 1b0;elsedin_dly < d…

307k star, 免费的编程书籍 free-programming-books

307k star, 免费的编程书籍 free-programming-books 分类 开源分享 项目名: free-programming-books -- 各种编程语言免费学习资源 Github 开源地址&#xff1a; https://github.com/EbookFoundation/free-programming-books 查找页面&#xff08;英文&#xff09;&#xff…

tigramite教程(七)使用TIGRAMITE 进行条件独立性测试

文章目录 概述1 连续数值变量1.1 ParCorr 偏相关&#xff08;ParCorr类&#xff09;1.2 鲁棒偏相关&#xff08;RobustParCorr&#xff09;非线性检验1.3 GPDC1.4 CMIknn 2a. 分类/符号时间序列2b. 混合分类/连续时间序列多变量X和Y的测试 概述 这个表格概述了 X ⊥ Y ∣ Z X\…

c语言文件操作(超详细)

前言 这次的博客&#xff0c;可以让大家快速掌握文件操作&#xff0c;方便大家快速找到不懂的内容 文件操作的作用以及基础 1. 为什么使用文件&#xff1f; 如果没有文件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&…

计算机笔记(3)续20个

41.WWW浏览器和Web服务器都遵循http协议 42.NTSC制式30帧/s 44.三种制式电视&#xff1a;NTSC&#xff0c;PAL&#xff0c;SECAM 45.IP&#xff0c;子网掩码白话文简述&#xff1a; A类地址&#xff1a;取值范围0-127&#xff08;四段数字&#xff08;127.0.0.0&#xff09…

第十三届蓝桥杯大赛软件赛省赛CC++大学B组

第十三届蓝桥杯大赛软件赛省赛CC 大学 B 组 文章目录 第十三届蓝桥杯大赛软件赛省赛CC 大学 B 组1、九进制转十进制2、顺子日期3、刷题统计4、修建灌木5、x进制减法6、统计子矩阵7、积木画8、扫雷9、李白打酒加强版10、砍竹子 1、九进制转十进制 计算器计算即可。2999292。 2、…

Spoon Taking Problem(c++题解)

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

开机自启动

对win10,给一种开机自启动的设置方法: 1. winr 打开 2. 输入shell:startup打开 开始\程序\启动 3. 把想要自启动的应用的快捷方式放在这里即可 亲测有用

2024年计算机学科夏令营预推免信息最全汇总(包括计算机本学科和交叉学科)

我在看到新的夏令营信息后会及时更新其中这个表格&#xff0c;表格已经存放在百度网盘中了&#xff0c;下面是一张截图&#xff1a; 下面是存放表格的百度网盘地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1damn4jnG8r-XPe0HhvBRbw?pwd9b0h 提取码&#xff1a;9…

【JavaWeb】百度地图API SDK导入

百度地图开放平台 | 百度地图API SDK | 地图开发 (baidu.com) 登录注册&#xff0c;创建应用&#xff0c;获取AK 地理编码 | 百度地图API SDK (baidu.com) 需要的接口一&#xff1a;获取店铺/用户 所在地址的经纬度坐标 轻量级路线规划 | 百度地图API SDK (baidu.com) 需要的…

MySQL-SQL编写练习:基本的SELECT语句

基本的SELECT语句 1. SQL的分类 DDL:数据定义语言。CREATE \ ALTER \ DROP \ RENAME \ TRUNCATEDML:数据操作语言。INSERT \ DELETE \ UPDATE \ SELECT &#xff08;重中之重&#xff09;DCL:数据控制语言。COMMIT \ ROLLBACK \ SAVEPOINT \ GRANT \ REVOKE 学习技巧&#xf…

【测试篇】测试用例

文章目录 前言具体设计测试用例等价类边界值场景设计法判定表&#xff08;因果图&#xff09;正交排列&#xff08;用的非常少&#xff09;错误猜测法 前言 什么是测试用例&#xff1f;&#xff1f; 测试用例是针对软件系统或应用程序的特定功能或场景编写的一组步骤&#xf…

后端返还二进制excl表格数据时候,如何实现在前端下载表格功能及出现表格打开失败的异常处理。

背景&#xff1a; 后端返还一个二进制流的excl表格数据&#xff0c;前端需要对其解析&#xff0c;然后可提供给客户进行下载。 思路&#xff1a;把二进制流数据转换给blob对象&#xff0c;然后利用a标签进行前端下载。 代码&#xff1a; 后端返还 类似如下的数据 前端代码…

电商技术揭秘六:前端技术与用户体验优化

文章目录 引言一、前端技术在电商中的重要性1.1 前端技术概述1.2 用户体验与前端技术的关系 二、响应式设计与移动优化2.1 响应式设计的原则2.2 移动设备优化策略2.3 响应式设计的工具和框架 三、交互设计与用户体验提升3.1 交互设计的重要性3.2 用户体验的量化与优化3.3 通过前…

AI绘画:使用Stable Diffusion ComfyUI进行换脸:IPAdapter FaceID全面教程

在数字艺术和媒体编辑领域&#xff0c;换脸技术已经成为一种流行且强大的工具。它允许创作者将一个人物的面部特征无缝地转移到另一个人物上&#xff0c;创造出令人信服的视觉作品。Stable Diffusion ComfyUI提供了一个高效的平台&#xff0c;让用户能够轻松地实现换脸。本文将…