今天我们来谈一谈素数的判定。

对于每一个OIer来说,在漫长的练习过程中,素数不可能不在我们的眼中出现,那么判定素数也是每一个OIer应该掌握的操作,那么我们今天来分享几种从暴力到高效的判定方法。


1.直观判断法

因为这种方法其实就是我们平常所说的暴力法。根据素数的定义,不能被2~n-1之内的数整除的整数n就被称为素数。所以我们从2跑到n-1,每次取模判断即可,这是最直观的一种方法,代码如下:

bool isPrime_1(int num)
{
    int tmp=num-1;
    for(int i=2;i<=tmp;i++)
      if(num%i==0)
         return 0;
    return 1;
}

2.直观判断优化法

上述判断方法,明显存在效率极低的问题。对于每个数n,其实并不需要从2判断到n-1,我们知道,一个数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),据此,上述代码中并不需要遍历到n-1,遍历到sqrt(n)即可,因为若sqrt(n)左侧找不到约数,那么右侧也一定找不到约数!所以从2跑到sqrt(n)就可以了。代码如下:

bool isPrime_2(int num)
{
     int tmp=sqrt(num);
     for(int i=2;i<=tmp;i++)
        if(num%i==0)
          return 0;
     return 1;
}

3.另一种方法(没想名字)

这个方法我也忘记是在哪一篇博客上看到过的了,如果博主看到了联系我来补版权引用

首先看一个关于质数分布的规律:大于等于5的质数一定和6的倍数相邻。例如5和7,11和13,17和19等等;

证明:令x≥1,将大于等于5的自然数表示如下:

······ 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ······

明显可以看到,不在6的倍数两侧,即6x两侧的数为6x+2,6x+3,6x+4,由于2(3x+1),3(2x+1),2(3x+2),所以它们一定不是素数,再除去6x本身,显然,素数要出现只可能出现在6x的相邻两侧。这里要注意的一点是,在6的倍数相邻两侧并不一定就是质数。

此时判断质数可以以6为单位快进,即将方法(2)循环中i++步长加大为6,加快判断速度,原因是,假如要判定的数为n,则n必定是6x-1或6x+1的形式,对于循环中6i-1,6i,6i+1,6i+2,6i+3,6i+4,其中如果n能被6i,6i+2,6i+4整除,则n至少得是一个偶数,但是6x-1或6x+1的形式明显是一个奇数,故不成立;另外,如果n能被6i+3整除,则n至少能被3整除,但是6x能被3整除,故6x-1或6x+1(即n)不可能被3整除,故不成立。综上,循环中只需要考虑6i-1和6i+1的情况,即 循环的步长可以定为6,每次判断循环变量k和k+2的情况即可。

代码实现也很简单,不过需要注意的是有两种情况需要特判:

1.这个数是1,需要返回false;

2.这个数是2或3,需要返回true;

其他的按照上面的思路打出来就对了,代码如下:

bool isPrime_3(int num)
{
	 if(num==1)
		return 0;
     if(num==2||num==3)
        return 1;
     if(num%6!=1&&num%6!=5)
        return 0;
     int tmp=sqrt(num);
     for(int i=5;i<=tmp;i+=6)
        if(num%i==0||num%(i+2)==0)
           return 0;
     return 1;
}

接下来来测试一下用时;

注意:下面的用时是指从1~n分别判定是不是素数,不是判定一次!

那么就先把数据范围调到40W;

运行结果:



很明显,方法1实在太慢了!但是!虽然方法2已经很快速了,但耗时依然是方法3的三倍多!足以证明第三种方法的快速。

那接下来单独比较方法2和方法3,把n调到1000w试试、

运行结果:



数据到了1000w的时候,方法3完全展示出了它的优势,这种用时在判定素数的方法中是非常节省用时得了。

看懂了上面的方法,分别用着去试一下过这道题目:

P3383 【模板】线性筛素数

ov.

【素数的判定-从暴力到高效】-C++的更多相关文章

  1. 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)

    关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...

  2. 『素数 Prime判定和线性欧拉筛法 The sieve of Euler』

    素数(Prime)及判定 定义 素数又称质数,一个大于1的自然数,除了1和它自身外,不能整除其他自然数的数叫做质数,否则称为合数. 1既不是素数也不是合数. 判定 如何判定一个数是否是素数呢?显然,我 ...

  3. Problem Description——用c语言实现素数的判定

    Problem Description 对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x,y)(-39<=x<y<=50),判定该表达式的值是否都为素数. Inp ...

  4. POJ 2739 Sum of Consecutive Prime Numbers( *【素数存表】+暴力枚举 )

    Sum of Consecutive Prime Numbers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19895 ...

  5. hdu 1431 素数回文(暴力打表,埃托色尼筛法)

    这题开始想时,感觉给的范围5 <= a < b <= 100,000,000太大,开数组肯定爆内存,而且100000000也不敢循环,不超时你打我,反正我是不敢循环. 这题肯定得打表 ...

  6. code vs1706 求合数和(数论 素数的判定)

    1706 求合数和  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解  查看运行结果     题目描述 Description 用户输入一个数,然后输出 ...

  7. code vs1436 孪生素数 2(数论+素数的判定)

    1436 孪生素数 2  时间限制: 2 s  空间限制: 1000 KB  题目等级 : 白银 Silver 题解  查看运行结果     题目描述 Description 如m=100,n=6 则 ...

  8. 【素数判定/筛法进阶算法】-C++

    今天我们来谈一谈素数的判定/筛法. 对于每一个OIer来说,在漫长的练习过程中,素数不可能不在我们的眼中出现,那么判定/筛素数也是每一个OIer应该掌握的操作,那么我们今天来分享几种从暴力到高效的判定 ...

  9. 【BZOJ1053】[HAOI2007]反素数ant 暴力

    [BZOJ1053][HAOI2007]反素数ant Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满足:g(x)>g(i) ...

随机推荐

  1. Centos重启关机命令

    Linux centos重启命令: 1.reboot   普通重启 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 10 过10分钟自动重启(root用户 ...

  2. Android 联系人导入导出(VCard格式)

    之前在Android Contact 导入导出 vcf格式(不依赖第三方库)记录了一下依赖Android sdk中的功能导入导出联系人(第一次做java项目内容,有些地方的记录是否正确,暂时我也不知道 ...

  3. storm(二)消息的可靠处理

    storm 通过 trident保证了对消息提供不同的级别.beast effort,at least once, exactly once. 一个tuple 从spout流出,可能会导致大量的tup ...

  4. LINQ学习笔记(三)

    下面对各子句解释 from子句:查询表达式的开始子句,查询表达式必须以from子句开头. 格式:from u in source 其中u表示范围变量,它表示源序列中的每个后续元素,source为数据源 ...

  5. 解释下Func<T, bool> exp

    比如 interface IRepository<T> where T:class { IEnumerable<T> FindAll(Func<T, bool> e ...

  6. WebAPI服务端内嵌在CS程序里面

    有时候我们不需要将WebAPI发布到iis上运行,需要将webapi内嵌到cs程序内部,随程序一起启动,其实比较简单,需要一个类,如下 public class Startup { public st ...

  7. MFC中的模态对话框与非模态对话框,模态对话框测试

    http://blog.csdn.net/u010839382/article/details/52972427 http://blog.csdn.net/u010839382/article/det ...

  8. Spring Type Conversion(Spring类型转换)

    Spring Type Conversion(Spring类型转换) 1:概述: Spring3引入了core.convert包,提供了通用类型转换系统,定义了实现类型转换和运行时执行类型的SPI. ...

  9. linux上java和golang环境变量的设置

    JAVA环境变量   (1).打开~/.bashrc完成环境配置( 作用类似于/etc/bashrc, 只是针对用户自己而言,不对其他用户生效.)       文件追加            expo ...

  10. linux 十五个原理知识点

    DNS系统架构与解析原理http协议通信原理TCP/IP的3次握手和四次断开原理MySQL主从同步原理Nginx配合php的fastcgi工作原理Lvs的4种模式工作原理Memcached工作原理(内 ...