首页 > 其他分享 >筛选质数的三个方法:1.素数判断,2埃氏法,3欧拉法。

筛选质数的三个方法:1.素数判断,2埃氏法,3欧拉法。

时间:2024-08-04 08:56:21浏览次数:17  
标签:埃氏法 筛法 int 合数 素数 埃氏 筛选 质数

文章目录

前言

一、素数是什么?

二、算法使用原理

1.合数:合数除了1和它本身以外,还有其他因数。与素数相对,素数只有1和它本身两个因数,而合数则至少有三个因数。

2.我们理解了合数的概念后,可以知道一个合数可以由至少三个因数构成如,6=1*2*3,说明所有素数的倍数都可以是合数,那么我们用到的埃氏筛就是利用这个原理将所有合数标记。

三,埃氏筛

一、定义与背景

二、核心原理

三、算法优势与不足

四、结论

2.代码展示

四,欧拉筛

欧拉筛法选素数的核心思想

欧拉筛法在埃氏筛法上的优化

总结

题目展示:来自力扣的3233题​

思路

代码

写法二


 


前言

在进行计算机编程题的练习的时候,大家多少都会遇到素数判断的问题。那么这篇文章将告诉大家判断素数的方法和一些计数的技巧,以及一些其他的关于求素数题目,和优化代码中的一些地方,制作不易求个免费赞。

一、素数是什么?

素数(Prime number),又称质数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。换句话说,一个大于1的自然数,如果只能被1和它本身整除,那么这个数就是素数。例如,2、3、5、7、11等都是素数,因为它们都只能被1和它们自己整除。而4、6、8、9等则不是素数,因为它们除了1和自身外,还能被其他自然数整除。

素数在数论中扮演着非常重要的角色,许多数学定理和猜想都与素数有关。例如,著名的哥德巴赫猜想就断言每一个大于2的偶数都可以写成两个素数之和。此外,素数也是加密技术中广泛使用的数学工具,如RSA加密算法就依赖于大素数的生成和分解的困难性。

二、算法使用原理

1.合数:合数除了1和它本身以外,还有其他因数。与素数相对,素数只有1和它本身两个因数,而合数则至少有三个因数。

2.我们理解了合数的概念后,可以知道一个合数可以由至少三个因数构成如,6=1*2*3,说明所有素数的倍数都可以是合数,那么我们用到的埃氏筛就是利用这个原理将所有合数标记。

三,埃氏筛

埃氏法筛选素数的核心原理可以归纳为以下几点:

一、定义与背景

埃拉托斯特尼筛法(Sieve of Eratosthenes),简称埃氏筛法,是一种简单且年代久远的筛法,用来找出一定范围内所有的素数。该算法由古希腊数学家埃拉托斯特尼提出,是一种基于素数的性质进行筛选的算法。

二、核心原理

  1. 初始化:首先,将待在的素数,通常使用一个布尔数组来表示,数组的下标对应自然数,数组的值表示该下标对应的筛选范围内的所有数都视为潜数是否为素数(true表示是素数,false表示不是素数)。

  2. 筛选过程

    • 从最小的素数2开始,将其所有的倍数(除了2本身)都标记为非素数(即将对应数组位置的值设为false)。这是因为素数的定义是只能被1和自身整除的数,所以任何素数的倍数都不可能是素数。
    • 接着,找到下一个未被标记为非素数的数(即下一个素数),重复上述过程,继续标记其所有倍数为非素数。
    • 这个过程一直持续,直到遍历完所有待筛选的数或者当前素数的平方大于待筛选范围的最大值时停止。因为如果一个合数n有除了1和它本身以外的因数,那么这些因数中必然有一个不大于sqrt(n)(算术基本定理)。所以,当一个素数的平方大于待筛选范围的最大值时,就可以确定剩下的数都是素数了。
  3. 结果输出:最后,未被标记为非素数的数就是素数,可以通过遍历布尔数组来输出这些素数。

三、算法优势与不足

优势

  • 相对于其他简单的素数筛选方法(如试除法),埃氏筛法能够更快速地找出一定范围内的所有素数。
  • 算法实现简单,易于理解和编程。

不足

  • 当筛选范围较大时,虽然算法的时间复杂度相对较低(接近O(nloglogn)),但空间复杂度较高,需要额外的空间来存储每个数的状态。
  • 算法在筛选过程中可能会重复标记某些数为非素数(例如,一个数可能会同时被多个素数的倍数所标记),这虽然不影响最终结果的正确性,但会增加一些不必要的计算量。

四、结论

埃氏筛法是一种简单有效的素数筛选方法,其核心原理在于利用素数的性质来逐步排除非素数,从而得到所有素数。尽管该方法在筛选范围和空间使用上存在一定的限制,但在实际应用中仍然具有广泛的用途和价值。

2.代码展示

其中的  j=i*2;可以改成i*i因为写法不一样,原因是因为1*2*3和1*3*2的答案是一样的,所以用i*2会造成重复,但是影响不大,注意方便理解。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	  int n;
	  cin>>n;/范围2-n;
	  int prime[n+1]={0};标记数组,可以用bool prime[n+1];
	  int ans=0;
	  for(int i=2;i<=n;i++)
	  {
	  	if(!prime[i])//如果是素数
	  	{
	  		for(int j=i*2;j<=n;j=j+i)//素数的倍数都是合数,原因在开始介绍了。为什么是j=j+i因为是倍数增加。注意改变的是j不是i。i相当于素数i*2就是一倍。
	  		{
	  		prime[j]=1;//对合数进行标记。
			}
		  }
	  }
	  for(int i=2;i<=n;i++)//遍历,没有标记的就说素数
	  {
	  	if(prime[i]==0) ans++;
	  }
	  cout<<ans;
	  return 0;
}



//优化版; 对答案的储存进行的了优化,利用了前缀合。
#include<bits/stdc++.h>
using namespace std;
int main()
{
	  int n;
	  cin>>n;
	  int prime[n+1]={0};//标记 
	  int sum[n+1]={0};
	  int ans=0;
	  for(int i=2;i<=n;i++)
	  {
	  	if(!prime[i])//如果是素数
	  	{
	  		sum[i]=sum[i-1]+1;//前缀和求当前位置的素数有多少个 
	  		for(int j=i*2;j<=n;j=j+i)//核心 标记合数 如12=2*2*3;12=2*6;<=n表面不超过最大范围 
	  		{					//成倍增加 
	  			prime[j]=1;
			}
		  }
		  else
		  {
		  	sum[i]=sum[i-1];//如果不是素数继承前面的状态。 
		  }
	  }
	  cout<<sum[n];
	  return 0;
}

四,欧拉筛

面对埃氏法的不足,我们又衍生出一种优化的算法欧拉筛。

欧拉筛法(Euler's Sieve)和埃氏筛法(Sieve of Eratosthenes)都是用于在给定范围内快速筛选出所有质数的算法。欧拉筛法作为埃氏筛法的优化版本,在效率上有了显著提升。以下是欧拉筛法选素数的核心思想以及在埃氏筛法上的优化点:

欧拉筛法选素数的核心思想

欧拉筛法的核心思想在于确保,从而避免了重复筛选,提高了算法的效率。具体来说,当遍每个合数只被其最小的质因子筛掉一次历到一个数i时,欧拉筛法会使用小于等于i的所有已知质数prime[j]去筛i*prime[j](其中j从0开始,且prime[j]≤sqrt(i)),但这里有一个关键优化:当i能被prime[j]整除时(即i%prime[j]==0),就停止用更大的质数去筛i的倍数。这是因为如果继续用更大的质数筛,那么筛掉的将是i的倍数与更大质数的乘积,而这个乘积的最小质因子仍然是prime[j],这会导致重复筛选(下面避免重复筛选解释了)。注意储存素数的数组是递增的,所有要从头遍历,才能保证被最小质因数筛掉。

欧拉筛法在埃氏筛法上的优化

  1. 避免重复筛选
    • 埃氏筛法中,一个合数可能会被它的多个质因子重复筛选多次(例如,30=2*15=3*10=5*6,在埃氏筛法中,30会被2、3、5都筛一遍)。而欧拉筛法通过确保每个合数只被其最小的质因子筛掉一次,从而避免了这种重复筛选。(解决方法就是开了一个数组储存素数)
  2. 时间复杂度降低
    • 埃氏筛法的时间复杂度为O(nloglogn),而欧拉筛法由于避免了重复筛选,其时间复杂度接近O(n),是一种非常高效的质数筛选算法。
  3. 实现方式
    • 欧拉筛法通常采用两个数组:一个用于存储质数(prime数组),另一个用于标记一个数是否已经被筛掉(vis数组或类似的标记方式)。遍历从2到n的所有数,对于每个数i,如果它还未被筛掉(即是质数),则将其加入到prime数组中,并用prime数组中的每个质数去筛 i 的倍数,但遵循上述的关键优化。
  4. 代码
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    	  int n;
    	  cin>>n;
    	  int prime[n+1]={0};
    	  int sum[n+1]={0}; 
    	  int ans=0;
    	  for(int i=2;i<=n;i++)
    	  {
    	  	if(!sum[i]) prime[ans++]=i;//储存素数的数组。
    	  		for(int j=0;j<ans;j++)
                这里用素数数组的总数是因为我们调用的是下标
    	  		{
    	  			if(prime[j]*i>n) break;
    	  			sum[prime[j]*i]=1;
                       //这一步的解释,这里的i表示的不是素数,还是利用合数=1*x*y
                       //埃氏法是固定素数x,遍历y,而欧拉筛是固定y,就是这里的i,遍历素数数组,这 
                         就是我们为什么要存放素数
    	  			if(i%prime[j]==0) break;//判断是否能被最小质因数整除;
                    避免重复筛选,文章内有解释。
    			}
    	}
    	  cout<<ans;
    	  return 0;
    }

总结

欧拉筛法通过避免重复筛选,在埃氏筛法的基础上实现了时间复杂度的显著降低,是一种高效且实用的质数筛选算法。其核心思想在于确保每个合数只被其最小的质因子筛掉一次,从而提高了算法的效率。在实际应用中,欧拉筛法在处理大规模数据时表现出色,被广泛应用于密码学、数论、组合数学等领域。

题目展示:来自力扣的3233题

思路

根据题意,文章让我们找特殊数字,这个数字有三个因数,那么什么数只有有三个因数呢,肯定是质数的平方了,所有题目的真正意思是让我们找这个范围内质数的平方,如何简便运算呢,首先让我们找平方,那么可以先缩小范围,找可以开根号的数里面的质数,第一步就可以对范围进行预处理,然后套我们的素数筛选方法。

代码

写法二

喜欢偷懒。其实就是换欧拉筛法,主体都是一样的,优化版本也是,靠各位编程之星自己解决了,留点思考量。

感谢点赞收藏。

标签:埃氏法,筛法,int,合数,素数,埃氏,筛选,质数
From: https://blog.csdn.net/2301_81834780/article/details/140889839

相关文章

  • PAT 乙级 真题练习 1013 数素数
    问题描述:题目描述:1013数素数分数20  作者 CHEN,Yue  单位 浙江大学令Pi​表示第i个素数。现任给两个正整数M≤N≤104,请输出PM​到PN​的所有素数。输入格式:输入在一行中给出M和N,其间以空格分隔。输出格式:输出从PM​到PN​的所有素数,每10......
  • 镜面质数 题解
    题目id:20313题目描述如果一个质数镜像反转(即将该数各个位上数字反转)后仍然是质数,那么就称这个质数为镜像质数。例如质数\(13\)反转后为\(31\),则\(13\)为一个镜像质数。现在给定一个整数\(N\),请求出整数\(1\simN\)范围内有几个镜像质数。注意:求范围内的镜像质数时,质数和镜像反......
  • leetcode数论(2523. 范围内最接近的两个质数)
     前言经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。现阶段开始专项练习。描述给你两个正整数 left 和 right ,请你找到两个整数 num1 和 num2 ,它们满足:left<=nums1<nums2<=right  。nums1 和 nums2 都是 质数 。nums2-nums1......
  • 【素数判断并打印】求100以内的素数
    求100以内的素数并打印,使用C语言实现实现代码:#include<stdio.h>intmain(){intnum,i,isPrime;printf("100以内的素数有:\n");for(num=2;num<100;num++){//从2开始到99isPrime=1;//假设num是素数//检查num是否......
  • 质数差列 题解
    题目id:20315题目描述驰骋宇宙的鱼大大找到了一个古遗迹,稍作研究后发现这是一个来着远古的质数星球文明遗迹,这个文明的特点是所有事物都和质数息息相关。于是,鱼大大赶紧列出了一堆的质数,以方便自己的研究。这天鱼大大找到了质数星球文明的一个遗迹仓库大门,正准备破解密码的同时......
  • zzuli1057: 素数判定
    题目描述输入一个正整数n,判断n是否是素数,若n是素数,输出”Yes”,否则输出”No”。注意:1不是素数。输入输入一个正整数n(n<=1000)输出如果n是素数输出"Yes",否则输出"No"。输出占一行。样例输入2样例输出Yes本题考察求素数的方法,我在文章结束列举了3种方法,以......
  • 如何在 Python 中创建正确显示素数的代码?
    素数是只能被自身和1整除的数。例如,数字5是素数,因为它只能被1整除和5.然而,数字6不是质数,因为它可以被整除通过2和3。编写一个名为is_prime的布尔函数,它接受一个整数作为参数如果参数是素数则返回true,否则返回false。使用程序中提示用户输入数字然后输......
  • 基础数论 质数与约数
    基础数论前置芝士:等比数列求和:\(S_n=a_0\frac{1-q^n}{1-q}\)质数与约数:整除与约数设\(n\)为非负整数,\(d\)为正整数,若\(\frac{n}{d}\)为整数,则称\(d\)整除\(n\),记为\(d\midn\)。此时,则称\(d\)是\(n\)的约数,或因数、因子;称\(n\)为\(d\)的倍数。质数......
  • C语言判断该数是否为素数
    素数判断方法:判断一个数是否为素数,即判断该数是否只能被1和自身整除,而不能被其他数整除。代码:#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>intisPrime(intnum){if(num<=1){return0;}for(inti=2;i*i<=num;i++){......
  • 第二届你要魔怔杯鲜花大赛参赛作品 - 运输小猫娘之再续 5k 传奇之寻找人道主义素数
    第二届你要魔怔杯鲜花大赛原文前情提要本章主角5k_sync_closer第一章从再续前缘到苦心寻找满足最优条件的人道主义美丽素数上回书说到,5k因为拯救大家被炸断了\(1000000007\)米中的十五千米,尽管大家的欢呼声如此热烈,就像大家的热量正在像烈火一样散发出来,但是5k却无心......