判断素数

这个随笔我是在写以下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;  
    } 
}  

 

 

posted @ 2018-03-16 23:07  我只有一件白T恤  阅读(214)  评论(0编辑  收藏  举报