目录

一、前言

二、埃氏筛与欧拉筛(线性筛)

1、问题描述

2、基本思路

(1)埃氏筛法

(2)欧拉筛法

三、题例

1、上链接

2、简单思路

3、代码

(1)埃氏筛python版

(2)欧拉筛python版


一、前言

对于学计算机的同学来说,学习算法是一件非常重要的事情,废话不多讲,我们来讲讲“埃氏筛与欧拉筛(线性筛)问题”。

二、埃氏筛与欧拉筛(线性筛)

1、问题描述

如题,给定一个范围 n,有 q 个询问,每次输出第 k 小的素数。

具体可见下面题目链接。

2、基本思路

先在 1~n 中筛选出所有素数(质数),然后再做判断。

显然朴素的判断素数的方法时间复杂度高,不可取。

下面介绍两种时间复杂度较低的方法,即埃氏筛法和欧拉筛法。(但是这个世界上没有天上掉馅饼的事情,我降低了时间复杂度,那么就必然要牺牲空间)

(1)埃氏筛法

首先将2到n范围内的整数写下来。

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

表中剩下的最小的数字就是3,他不能被更小的数整除,所以3是素数。

再将表中所有的3的倍数划去…… 以此类推,如果表中剩余的最小的数是m,那么m就是素数。

然后将表中所有m的倍数划去,像这样反复操作,就能依次枚举n以内的素数。

埃氏筛法的时间复杂度是0(n*log(logn))。

埃氏筛法的基本思想 :

从2开始,将每个质数的倍数都标记成合数,以达到筛选素数的目的。

因为随便一个合数的约数都不会大于自己,且必然存在有约数是素数的情况,那么我对规定范围内的数进行从小到大的判断,正好是能“划掉大的合数”且不会出现遗漏。

算法代码(C++):

#include<iostream>
using namespace std;//埃氏筛法
bool v[100001000]; //v[i]为0代表数i为素数
int cnt=0;void prime(int n){v[0]=v[1]=1;for(int i=2;i<=n;++i){ //注意这里也统计了等于n的数 if(!v[i]){cnt++;for(int j=i+i;j<=n;j+=i){ //注意这里也统计了等于n的数 v[j]=1;}}}
} int main(){int n;cin>>n;prime(n);cout<<cnt<<endl;return 0;
} 

对该代码稍作修改便可AC掉下面给出的力扣的例题。

(2)欧拉筛法

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

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

首先,任何合数都能表示成多个素数的积。所以,任何的合数肯定有一个最小质因子。我们通过这个最小质因子就可以判断什么时候不用继续筛下去了。

欧拉筛法的基本思想 :

在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。

算法代码(C++):

#include<iostream>
using namespace std;//欧拉筛法
int v[100001000]; //v[i]=a代表数i的最小质因数为a
int prime[600000];
int cnt=0;void is_prime(int n){v[0]=v[1]=1;for(int i=2;i<=n;++i){ //注意这里也统计了等于n的数 if(!v[i]){ //从小到大枚举,能保证如果v[i]==0,那么i就是素数 v[i]=i;prime[++cnt]=i;}//注意一点,i显然永远是大于或等于prime[j]的,但 v[i] 不一定//而一个质数的最小质因数也就是其本身,即prime[j]的最小质因数是prime[j] for(int j=1;j<=cnt;++j){//因为从小到大枚举,所以当前的大于,以后的一定大于 if(prime[j]>n/i||prime[j]>v[i])break; v[i*prime[j]]=prime[j];// i*prime[j] 代表当前数乘以之前出现的素数// v[i*prime[j]] 的最小质因数是prime[j]// 当 i%prime[j]==0 时,显然成立// 当 i%prime[j]!=0 时,又由于上面的 if 判断保证了 v[i]>=prime[j],所以也成立 /**解释上面的这个 if 判断条件第一个条件 prime[j]>n/i 用于防止越界第二个条件 prime[j]>v[i],如果 i 的最小质因子比prime[j]的最小质因子小,那么v[i*prime[j]]应该等于v[i],但是现在用当前数的最小质因子给 i*prime[j] 的最小质因子赋值会导致重复赋值,因为后面 i==(i*prime[j])/v[i] 的时候prime[i]能在不大于v[i]的情况下 v[i*prime[j]]=prime[j]也就是说,我们要保证prime[j]为最小质因子,这样能减少操作次数 */ }}
} int main(){int n,q;cin>>n>>q;is_prime(n);for(int i=0;i<q;++i){int k;cin>>k;cout<<prime[k]<<endl;}return 0;
} 

代码为何这样写看注释,解释得非常清楚了。(该代码能直接AC掉下面给出的洛谷的例题)

三、题例

1、上链接

【模板】线性筛素数 - 洛谷

力扣

2、简单思路

同上。

3、代码

(1)埃氏筛python版

class Solution:global vdef is_prime(self,n:int)->int:cnt=0v[0]=v[1]=1for i in range(2,n+1):if v[i]==0:cnt+=1for j in range(i+i,n+1,i):v[j]=1return cntif __name__=='__main__':v=[0]*10001000n=int(input())# print(type(n))res=Solution.is_prime(Solution,n)print(res)'''
下面的代码能AC掉力扣上的题:
class Solution:def countPrimes(self, n: int) -> int:v=[0]*10000000cnt=0v[0]=v[1]=1for i in range(2,n):if v[i]==0:cnt+=1for j in range(i+i,n+1,i):v[j]=1return cnt
'''

(2)欧拉筛python版

# 下面代码AC不了洛谷的例题,主要是因为空间的问题,算法思想和代码实现是没问题的
class Solution:global v,primedef is_prime(self,n:int)->None:cnt=0v[0]=v[1]=1for i in range(2,n+1):if v[i]==0:v[i]=icnt+=1prime[cnt]=ifor j in range(1,cnt+1):if prime[j]>n//i or prime[j]>v[i]:breakv[i*prime[j]]=prime[j]if __name__=='__main__':v=[0]*55001000prime=[0]*800100n,q=map(int,input().split())# print(type(n))Solution.is_prime(Solution,n)for _ in range(q):k=int(input())print(prime[k])

另一个模板python代码:

# 线性筛质数
N=1000010
n=int(input())
cnt=0 # 用来计算有几个素数
primes=[] # 用来存素数
def get_primes(n):global cnt,primesst=[False for i in range(N)] # 是否被筛过for i in range(2,n+1):if(st[i]==0): # 如果没被筛过 是素数primes.append(i) # 放到素数列表中cnt+=1for j in range(N):if(primes[j]>n//i): break # 枚举已经筛过的素数st[primes[j]*i]=1 # 将他们标为已经筛过了if(i%primes[j]==0): break
get_primes(n)
print(cnt)'''
(1)对于 visit[i*prime[j]] = 1 的解释: 这里不是用i的倍数来消去合数,而是把 prime里面纪录的素数,升序来当做要消去合数的最小素因子。
(2)对于 i%prime[j] == 0 就break的解释 :当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,所以才跳出循环。
举个例子 :i = 8 ,j = 1,prime[j] = 2,如果不跳出循环,prime[j+1] = 3,8 * 3 = 2 * 4 * 3 = 2 * 12,在i = 12时会计算。因为欧拉筛法的原理便是通过最小素因子来消除。
'''

以上,埃氏筛与欧拉筛(线性筛)

祝好

埃氏筛与欧拉筛(线性筛)相关推荐

  1. 筛质数—(朴素筛法、埃氏筛法、欧拉筛法(线性筛法))

    筛质数时首先要了解质数的定理:1~n中有  个质数 下面再来看具体算法: 1.朴素筛法: 直接把2~n-1中质数和合数的倍数都筛一遍,其代码如下所示: int primes[N],cnt=0; boo ...

  2. 中高级数论 [欧拉函数线性筛,二次剩余]

    欧拉函数线性筛 对于素数ppp, φ(p∗i)={p−1i=1p∗φ(i)p∣i(p−1)∗φ(i)p∤i\varphi (p*i)= \begin{cases} p-1& i=1\\ p*\ ...

  3. 快速求素数表——埃氏筛法与欧拉筛法

    快速求素数表--埃氏筛法与欧拉筛法 快速求素数表埃氏筛法与欧拉筛法 埃氏筛法 埃氏筛法原理 埃氏筛法时间复杂度 埃氏筛法代码求出1000000以内的素数并且输出n个素数 欧拉筛法 欧拉筛法原理 欧拉筛 ...

  4. 素数计算之埃氏筛法、欧拉筛法

    埃氏筛法 int main() {const int maxNumber=200;int isPrime[maxNumber];int i;int x;for (i=0;i<maxNumber; ...

  5. 素数筛法(传统普通、朴素筛法、埃式筛法、欧拉筛法(线性筛))

    素数筛法(普通.朴素筛法.埃式筛法.欧拉筛法) 1.题目 2.分析 3.代码 传统普通 朴素筛法 朴素筛法(6.14) 埃式筛法 埃式筛法(6.14) 欧拉筛法(线性筛) 欧拉筛法(线性筛 6.14) ...

  6. 线性筛与欧拉函数、莫比乌斯函数

    网上关于素数筛的资料很多,这里只是给出弱鸟整理的几个线性筛和应用. 最朴素的素数筛--埃拉托斯特尼筛法(Sieve of Eratosthenes) 复杂度 Olognlogn int primes[ ...

  7. 素数筛法详解:埃氏筛和欧拉筛

    文章目录 摘要 埃式筛 欧拉筛 超级详细的基础算法和数据结构合集: https://blog.csdn.net/GD_ONE/article/details/104061907 摘要 本文主要介绍埃氏 ...

  8. 筛选质数,埃氏筛和欧拉筛(线性筛)

    求len之内的所有的素数 除了比较常用的开根号的求法,还有两种更好的方法,埃氏筛和线性筛.其中埃氏筛更好理解,而线性筛(欧拉筛)不好理解但是更快. 埃氏筛 #include <bits/stdc ...

  9. 算法笔记--素数筛(朴素筛,埃式筛,欧拉筛)

    素数 素数也叫质数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数.如2 , 3 , 5 , 7 , 11等. 素数筛 素数筛即筛选出1~n内的素数的方法,这里介绍三种 常见的求素数 ...

最新文章

  1. c语言求跳水运动员成绩,跳水排名_C语言编程实例_C语言_最全面的网站教程
  2. SAP BMBC报表不能显示批次分类视图里的特性值
  3. 「后端小伙伴来学前端了」Vue中全局事件总线(GlobalEventBus)原理及探究过程
  4. React开发(272):try...catch..捕获
  5. LwIP应用开发笔记之三:LwIP无操作系统UDP客户端
  6. Spring Boot文档阅读笔记-Creating Asynchronous Methods解析
  7. C++11 并发指南六(atomic 类型详解四 C 风格原子操作介绍)
  8. kafka retries参数入门
  9. 【C++】【GADL】读取栅格数据(tif),遍历数组
  10. 多伦多大学Self-Driving Cars自动驾驶专项课程(十八)Proportional-Integral-Derivative(PID) Control
  11. 怎么把pdf文件转换成word方法分享
  12. 华为手机图标怎么变小_华为手机字太小看不清?那是你不会设置!四种方法让手机显示变大...
  13. sif4j 字符串拼接和占位符的区别
  14. 如何引用服务器lua文件,Lua教程(一):在C++中嵌入Lua脚本
  15. h5php大转盘抽奖,jQuery带次数带弹窗的大转盘抽奖代码(支持h5)
  16. IEEE认证Pdf格式失败问题
  17. php和thinkphp实现页面调转
  18. Source Insight主题美化插件
  19. 自己努力要学习啦(android的很多demo 总有你需要的)
  20. 你在任何领域都该了解的那些法则,超全面!

热门文章

  1. 全球土地利用数据ESRI 10m Land Cover 2020 in GEE(Google Earth Engine)
  2. 分布式相关问题总结(精选)
  3. Lesson 2 Thirteen equals one
  4. Python解析DBLP的xml文件
  5. 192.168.1.10/27,后面的27是什么意思,这样写限制的网络是哪些?
  6. 常数和基本初等函数的导数
  7. 测试/开发程序员的思考,突破变得更强......
  8. NLPCC2023 | 视频定位问答比赛CMIVQA赛题解析
  9. Latex中如何加粗字体 如何打出圆圈序号
  10. 「GXOI / GZOI2019」逼死强迫症——斐波那契+矩阵快速幂