zoukankan      html  css  js  c++  java
  • 判断素数

    这个随笔我是在写以下PAT上题目过来写的,以下是题目测试点

    >>点击进入PAT测试<<

    题目就是很简单就能AC,但是对于是判断素数这个问题似乎我一学C语言的时候就已经接触了,对于普通的先开根号在其范围内直接循环取余我就不重复了


    • 介绍第一种方法:

    摘抄来自huang_mao_xin的帖子

    证明:令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,加快判断速度,代码如下:
    bool Isprime(int num)
    {  
        if (num < 2)return false;
    
        //两个较小数另外处理  
        if (num == 2 || num == 3)
            return true;
    
        //不在6的倍数两侧的一定不是质数  
        if (num % 6 != 1 && num % 6 != 5)
            return false;
    
        int tmp = sqrt(num);
        //在6的倍数两侧的也可能不是质数  
        for (int i = 5; i <= tmp; i += 6)
        if (num %i == 0 || num % (i + 2) == 0)
            return false;
    
        //排除所有,剩余的是质数  
        return true;
    }  

    第一眼看到的时候感觉这种方法似乎真的很省时,但是拿PAT的测试没有通过,所以问题待定,以后补充


    • 第二个方法:叫Eratosthenes筛法,简称“筛法”

    原理:如果一个数是素数,那么这个数的倍数一定不是素数,把所有的非素数都去掉,但是这个算法会有冗余,算法效率要比O(n)低,这个方法适合用于筛选出1N的所有素数这类问题,但不适合用在数较大的情况。

    bool flag[N];
    void findPrime(int num){
        
        for (int i = 0; i <= num; i++){
            flag[i] = true;
        }
        flag[0] = flag[1] = false;
        for (int i = 2; i <= num; i++){
            if (!flag[i])   continue;
            for (int j = i*i; j <= num; j += i){
                flag[j] = false;
            }
        }
    }

     该算法较优化后:

    int a[1000005];
    void IsPrime(int num)
    {
        memset(a, -1, sizeof(a));
        a[0] = a[1] = 0;
        a[2] = -1;
        for (int i = 3; i <= num; i++)
            a[i] = i % 2 == 0 ? 0 : -1;
        int t = sqrt(num);
        for (int j = 3; j <= t; j++)
        if (a[j])
        for (int i = j*j; i <= num; i += 2*j)
            a[i] = 0;
    }

    下面这个是我认为改进很大的筛法:摘抄来着MoreWindows的原创文章

     贴段代码,详情点开链接好了

    bool flag[MAXN];  
    int primes[MAXN / 3], pi;  
    void GetPrime_2()  
    {  
        int i, j;  
        pi = 0;  
        memset(flag, false, sizeof(flag));  
        for (i = 2; i < MAXN; i++)  
        {  
            if (!flag[i])  
                primes[pi++] = i;  
            for (j = 0; (j < pi)  && (i * primes[j] < MAXN); j++)  
               flag[i * primes[j]] = true;  
        } 
    }  
  • 相关阅读:
    Markdown简介
    主动安全协议-广东标准(粤标)和江苏标准(苏标)的区别及平台开发
    机动车驾驶员计时培训系统平台技术规范
    DevOps 之路
    allinaws
    Dockerfile-For-Python
    Mac 添加vmware fusion nat网卡信息
    AWS 使用S3为Web站点
    AWS ALB实现80端口跳转443端口
    深入理解Service
  • 原文地址:https://www.cnblogs.com/zengguoqiang/p/8586319.html
Copyright © 2011-2022 走看看