ACM-判断素数

这篇文章我们将讨论有关如何求解素数,

素数:即只能被1及其本身整除的数。

方法一:暴力判断

对于一个数N是不是素数,可以通过2~n-1—进行枚举,如果n不能被整除,那么说明n就是素数。

/*注意两点:①n不能太大。②只需要判断n的根号次。*/

下面是判定素数的源代码:

#include <cmath>
int IsPrime(int n)
{
    for(int i=2; i<=sqrt(1.0*n); ++i)
        if(n%i == 0)
            return 0;
        return 1;
}

 

       很明显这样直接枚举判断的时间复杂度很高,下面讲一种高效的方法:筛法,如果用筛法构造素数,可以在很短的时间内算出10^6以内的所有素数。

方法二:筛法

       筛法的原理简单来说就是删除倍数,即对于不超过n的每一个非负整数p,删除2p,3p,4p,.....,这样处理完每一个p之后,剩下的没有被删除的就是素数,其实这也是素数定义的体现,即能被除了1和自身外的任何数整除的数都不是素数。

       时间复杂度:nlog(n)

下面是筛法的源代码:

#include <cmath>
#include <cstring>

constint MAXN = 1e6;
int vis[MAXN+1];
int prime[MAXN+1];

void IsPrime(int n)

{
    int i, j;
    int m = sqrt(n+0.5);
    memset(vis, 0, sizeof(vis));
    memset(prime, 0, sizeof(prime));
    for(i=2; i<=m; ++i)
        if(!vis[i])
       {
            prime[i] = 1;  // 如果i为素数
            for(j=i*i; j<=n; j+=i)
               vis[j] = 1;
       }
    for(; i<=n; ++i)
       if(!vis[i])
            prime[i] = 1;
}

                     

 

以上算法并不是最快的,因为存在重复的筛数,比如2和4来说,都将8,12,16,……,筛除了。要保证不会重复筛除每一个数,即让算法保持线性,可以从奇偶性方面入手。

const int MAXN = 1e6;
int prime[MAXN+1];

void IsPrime(int n)

{
    int i,j,k;
    int half = n/2;
    int sn = sqrt(n+0.5);
    memset(prime,0,sizeof(prime));
    for (i = 0; i < half; i++)
        prime[i] = 1;
    for (i = 0; i < sn; i++)
        if(prime[i])
        {
            for(k=i+i+3,j=k*i+k+i; j<half; j+=k)
                prime[i] = 0;
        }
}

 

posted @ 2018-01-24 14:59  jazyer  阅读(287)  评论(0编辑  收藏  举报