注:本篇文章已搬至个人博客中, 点击前往

素数(质数)的判断在算法问题中经常遇到,这里小结几种常用的判断方法。

素数(质数)的定义

首先,我们来看一下素数(质数)的定义:质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。

方法一

我们可以从它的定义得到判断素数的 第一个方法: 从 222 到 n−1n - 1n−1, 判断是否存在能被n整除的数,既(n%i==0,2<=i<=n−1)(n \% i == 0, 2 <= i <= n - 1)(n%i==0,2<=i<=n−1),如果有就不是素数,否则为素数。

(这里为了比较几种算法的性能,用计算出1000,000中有多少个素数所需的时间作为性能比较的参考。附上本篇博文所有程序的运行环境(机房哈哈):系统windows xp, cpu:E5200,2.50GHZ, 0.99GB内存,IDE:codeblocks)

首先,可以先作一个小的优化,既除2以外,只需判断所有的奇数是否是素数。

//素数判断方法1
#include<stdio.h>
#include<time.h>
#define Max 1000000
int main()
{int sum = 1;//2单独处理,sum为素数的个数for(int i = 3; i <= Max; i+=2){//因为偶数除了2之外都不是素数(质数),所以只需判断奇数,从3开始每次+2int j;for(j = 2; j < i; j++)//判断if(i%j == 0)break;if(j == i)sum++;}printf("Time used = %0.2f s\n",(double)clock()/CLOCKS_PER_SEC);//获取程序运行的时间printf("%d",sum);return 0;
}

程序的时间复杂度为O(n2n^2n2)。
运行结果

结果表明n的数量级太大时,不宜采用该方法。
同时也可以得到结论1000,0001000,0001000,000中有784987849878498个素数。

接下来的方法其实都是对上述方法进行优化,可以很好地降低时间复杂度。
利用以下结论:对正整数nnn,如果用2到 n\sqrt{n}n​之间的所有整数去除,均无法整除,则nnn为质数。

方法二

//素数判断方法2
#include<stdio.h>
#include<time.h>
#include<math.h>
#define Max 1000000
int main()
{int sum = 1;for(int i = 3; i <= Max; i+=2){//因为偶数除了2之外都不是素数(质数),所以只需判断奇数,从3开始每次+2int j;for(j = 2; j <= (int)sqrt(i); j++)//利用上述结论判断if(i%j == 0)break;if(j > (int)sqrt(i))sum++;}printf("Time used = %0.2f s\n",(double)clock()/CLOCKS_PER_SEC);printf("%d",sum);return 0;
}

程序的时间复杂度为O(n\sqrt{n}n​)。
运行结果

可以看到程序的运行时间已经大幅度地降低。

接下来的方法需要利用到孪生素数的一些特点和结论。

孪生素数

孪生素数:孪生素数指的是间隔为 222 的相邻素数。
1.当n>=6n >= 6n>=6, n−1n - 1n−1 和 n+1n + 1n+1 为孪生素数,那么n 一定是6的倍数。
Proof :

∵n−1,n+1是素数,也即n−1和n+1是奇数∴n是偶数,n是2的倍数。设n不是3的倍数,即n=3k+1或n=3k+2。(i)当n=3k+1时,那么n−1=3k,已经与n−1是素数矛盾。(ii)当n=3k+2时,那么n+1=3(k+1),已经与n+1是素数矛盾。综上所述,n是3的倍数。∵n既是2的倍数,又是3的倍数∴n是6的倍数。\begin{aligned} &∵ n - 1, n + 1是素数,也即 n - 1 和 n + 1是 奇数\\ &∴n 是 偶数,n 是 2 的倍数。\\ &设 n 不是 3 的倍数,即 n = 3k + 1 或 n = 3k + 2。\\ &(i)当 n = 3k + 1 时,那么 n - 1 = 3k,已经与 n - 1 是素数矛盾。\\ &(ii)当 n = 3k + 2 时, 那么 n +1=3(k + 1),已经与 n + 1是素数矛盾。\\ &综上所述,n 是 3 的倍数。\\ &∵n既是2的倍数,又是3的倍数\\ &∴n 是6的倍数。\\ \end{aligned} ​∵n−1,n+1是素数,也即n−1和n+1是奇数∴n是偶数,n是2的倍数。设n不是3的倍数,即n=3k+1或n=3k+2。(i)当n=3k+1时,那么n−1=3k,已经与n−1是素数矛盾。(ii)当n=3k+2时,那么n+1=3(k+1),已经与n+1是素数矛盾。综上所述,n是3的倍数。∵n既是2的倍数,又是3的倍数∴n是6的倍数。​

推论1 : 当 x>=1x >= 1x>=1, (6x−1)(6x - 1)(6x−1)或 (6x+1)(6x + 1)(6x+1)不是素数时,它们的质因子不包括2和3的倍数,因为2(3x)−1,3(2x)−1,2(3x)+1,3(2x)+12(3x) - 1, 3(2x) - 1,2(3x) + 1, 3(2x) + 12(3x)−1,3(2x)−1,2(3x)+1,3(2x)+1。

2.素数的分布规律:当n>=5n >= 5n>=5时,如果n为素数,那么n%6=1∣∣n%6=5n \% 6 = 1 || n \% 6 = 5n%6=1∣∣n%6=5,即n一定出现在6x(x≥1)6x(x≥1)6x(x≥1)两侧。(就是说大于等于5的素数一定是分布在6倍数的左右两侧,但在6倍数左右两侧的数不一定是素数)
Proof:
可以把6x附近的数用以下方式表示:……(6x−1),6x,6x+1,2(3x+1),3(2x+1),2(3x+2),6x+5,6(x+1)……不在6x两侧的数为:2(3x+1),3(2x+1),2(3x+2),它们不是素数,所以素数出现在6x的两侧。\begin{aligned} &可以把6x附近的数用以下方式表示:\\ &……(6x - 1), 6x, 6x+1, 2(3x+1), 3(2x+1), 2(3x +2), 6x + 5, 6(x+1)……\\ &不在6x两侧的数为: 2(3x+1), 3(2x+1), 2(3x +2),它们不是素数,所以素数出现在6x的两侧。\\ \end{aligned} ​可以把6x附近的数用以下方式表示:……(6x−1),6x,6x+1,2(3x+1),3(2x+1),2(3x+2),6x+5,6(x+1)……不在6x两侧的数为:2(3x+1),3(2x+1),2(3x+2),它们不是素数,所以素数出现在6x的两侧。​
  有了以上的理论基础,我们可以对方法2进一步地优化,首先不在6x6x6x左右的数2,32,32,3单独处理,接下来只要判断6x6x6x两侧的数是否为素数。因为合数总是可以写成素数的乘积,那么我们直接用n去除以质数就可以达到很好地优化目的。而质数一定是 6x6x6x 两侧的数(推论一已证明了当n>=5n >= 5n>=5时,n不是素数时,n 不含质因子2,3) , 6x6x6x 两侧的数是大于素数的集合,因此可以用 nnn 除以 6x6x6x 两侧的数即if(n % i == 0 || n % (i + 2) == 0)时,不是素数。

方法三:基于孪生素数方法筛除

//素数判断方法3
#include<stdio.h>
#include<time.h>
#include<math.h>
#define Max 1000000
using namespace std;
int main()
{int sum = 1;//已经将2单独处理int flag = 0;for(int i = 3; i <= Max; i+=2){if(i == 3)//3单独处理sum++;if(i % 6 != 1 && i % 6 !=5)continue;//不是6x两侧的数不是素数for(int j = 5; j <= (int)sqrt(i); j+=6)//对6x两侧的数进行判断if(i%j == 0 || i%(j + 2) ==0){flag = 1;break;}if(flag == 1){flag = 0;continue;}sum++;}printf("Time used = %0.2f s\n",(double)clock()/CLOCKS_PER_SEC);printf("%d",sum);return 0;
}

运行结果:

方法3运行结果表明比方法2快速了许多倍,已经是很高效的算法了。

方法四:普通筛选法

更新日记:2018/1/31增加普通筛选法
比上面几种方法更快,也比较容易理解。
思想: 一个素数的倍数都不是素数。
时间复杂度: O(nloglogn)

#include<iostream>
#include<vector>
using namespace std;
const int maxt = 1000000;
vector<bool>prime;
int main()
{prime.resize(maxt,1);prime[0] = prime[1] = 0;//1是素数,0是非素数for(int i = 2; i*i <= prime.size(); i++){if(prime[i] == 1)for(int j = i*2; j <= prime.size(); j += i){prime[j] =  0;}}return 0;
}

相关习题:蓝桥杯 Torry的困惑(基本型)

【算法】素数(质数)判断方法相关推荐

  1. 素数(质数)判断方法

    https://blog.csdn.net/songyunli1111/article/details/78690447  ->通俗易懂的解释 标准版:大部分人都知道的比较快的方法:判断从2到s ...

  2. 【原创】【数论】质数判断方法汇总及证明(上-费马素性检测与卡迈克尔数)

    质数 一.定义: 对于一个整数p,除了1和p之外没有别的整因数的整数,称为质数. 若p为质数,则除p=1*p外没有别的分解方式. 二.性质: ≤n的质数粗略的有n/ln(n)个.(非常粗略,误差较大, ...

  3. 求素数(质数)的方法及时间复杂度的比较

    素数,又叫质数,定义是除了1和它本身以外不再有其他的因数 时间复杂度O(n) bool prime(int x){//判断x是不是质数,是返回true,不是返回false if(x<=1) re ...

  4. 详解素数(质数)的判断

    文章目录 一 什么是素数? 二 素数的判断方法 2.1 方法1 2.2 方法2 2.3 方法3 2.4 方法4 一 什么是素数? 质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整 ...

  5. Python|每日一练|素数对|优化算法|素数|素数对:找出素数对

    找出素数对 任意输入一个大于10的偶数,编程找出所有和等于该偶数的素数对 以下程序实现了这一功能,请你填补空白处内容: h = 0 def a(h): x = 0 for j in range(2, ...

  6. 判断素数(质数)高效算法

    最近看到一篇高效的素数判断算法文章,但是文章中有些部分写的还不够完整清晰,所以在此详细记录一下此算法理解过程.(理解此算法前应先明白使用 sqrt(num) 为判断条件判断素数的方法) 此算法产生的原 ...

  7. 判断一个数是否为质数/素数——从普通判断算法到高效判断算法思路

    定义:约数只有1和本身的整数称为质数,或称素数. 计算机或者相关专业,基本上大一新生开始学编程都会接触的一个问题就是判断质数,下面分享几个判断方法,从普通到高效. 1)直观判断法 最直观的方法,根据定 ...

  8. 代码实现:判断101-200之间有多少个素数(质数),并输出所有素数。 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。...

    package com.heima.Coding;/*判断101-200之间有多少个素数(质数),并输出所有素数.程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明 ...

  9. php判断质数,php如何判断是否为素数?判断素数的三种方法(代码示例)

    本篇文章给大家带来的内容是介绍php如何判断是否为素数?判断素数的三种方法(代码示例).有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助. 什么是素数? 质数又称素数.一个大于1的自然数 ...

最新文章

  1. RH5.4下samba共享配置实例(3)
  2. 基于Sentinel的Redis3.2高可用方案
  3. 学习官方示例 - System.TClass
  4. 这次是在没有外网yum仓库的情况下搭建内网yum仓库和无人值守pxe装机
  5. CTFshow 文件上传 web155
  6. LtScrollImageView:自动滚动的广告图片展示栏
  7. Golang和Ethereum中的big.Int
  8. 小小树微博制作记录笔记(一)
  9. 【项目源码分享】基于C++实现的小型数据库(Windows/Linux环境)
  10. PyTorch中的nn.Conv1d与nn.Conv2d
  11. java实现下功能载插件_javaweb项目插件实现机制
  12. [转]python新手必碰到的问题---encode与decode,中文乱码--转载
  13. 在centos6.5中安装github的客户端git
  14. php 修改文件的权限_php修改文件权限
  15. 解决 psftp local: unable to open 的问题
  16. python 百度识图_python 调用百度识图识取本地图片
  17. 企信下载的文件在哪里_Foobar2000(无损音乐播放器下载)(软件篇)
  18. 1118 Birds in Forest (25分)——(并查集)
  19. css3中自适应边框图片运用
  20. 策略模式(用策略模式实现我们淘宝,京东,美团等等简易满减活动)

热门文章

  1. 数据可视化查看2021城市GDP
  2. 今年嵌入式行业研究生应届生毕业大概薪资多少,大数据告诉你
  3. GBASE 8s数据库参数管理
  4. 华瑞IT学校:优秀Java工程师需要掌握八大技能
  5. 使用正则表达式匹配AA、AAA、AABB几个相同字符重复出现
  6. 移动端Web上传图片实践
  7. java毕业设计基地信息可视化(附源码、数据库)
  8. MHDD磁盘坏道扫描工具使用方法图解教程
  9. Vue.js在chrome游览器下下拉菜单无法响应
  10. wamp5 apache 配置好了 打localhost会出现index of 页面 解决