素数的求法

来源:互联网 发布:淘宝开店论坛 编辑:程序博客网 时间:2024/04/30 13:42

1.       素数:一个只有两个因子(1和本身)的大于1自然数,最小的素数为2

2.       按定义来判断某个数n是否为素数。

1.       解题思路:判断在2-sqrtn)的范围内是否有n的因子。如果有,则该数不为素数(即合数);否则该数就为素数。

2.       代码:

 

#include 

using namespace std;

bool isPrime(int n)

{

      bool prime= true  

      for(int i=2;i*i<=n;i++)

             if(n%i==0)    //nhas another divisor except 1 and n

             {

                    prime= false;

                    break;

             }

      return prime;

}

int main( )

{

      int n;

      cin>>n;

      if(isPrime(n))

             cout<<"yes"<<endl;

      else

             cout<<"no"<<endl;

      return 0;

}

     时间效率为:O(sqrt(n))

     *但是当要联系判断多个数是否为素数时,这种方法的效率就太低了。下面介绍另外一种效率略高的方法

 

3.筛选法求素数:

如果要连续判断大量的数是否为素数时,用筛选法是一种不错的方法,但是也有缺点(这点稍后再谈):

在介绍这种方法之前,你必须要明白任何一个素数都可以由多个合数组成。

      

1.       解题思路:

1.创建一个长度为n的数组,数组的下标就表示相应的数,其内的值表示该数是否为素数(0表示不是素数,1表示是素数)。

2.将下标为0和下标为1的数组内的内容标为0

3.2开始,直到p(2<=p<=sqrt(n)),把所有的kpkp<=nk=2,3……)都      标记为0(即为合数)。

4.输出数组中值为1的数的下标(即为1-n中所有的素数)

                   2.代码:

#include 

using namespace std;

void isPrime(int *prime,int n)

{

       for(int i=2;i*i<=n;i++)  

       {

              if(prime[i])  //从素数开始

              {

                     for(int j=2*i;j<=n;j+=i)   //下标为素数的倍数的数为a合数

                            prime[j]=0;

              }

       }

}

int main()

{

       int prime[101];

       for(int i=0;i<101;i++)

       {

              prime[i]=1;

       }

       prime[0]=0;

       prime[1]=0;

       isPrime(prime,100);

       for(int i=0;i<101;i++)

              if(prime[i]==1)    //1表示素数,0表示合数

                     cout<<i<<endl;

       return 0;

}

这种算法的时间复杂度小于n*sqrt(n);

这种方法有一个缺陷:

1.       如果判断1000个数是否为素数,但是这些数分布在(1*10^8,1*10^9)范围内时,会造成极大的空间浪费。

4.下面介绍一种可以节省空间的求素数的算法:

1.解题思路:

1.       定义一个数组,长度大约为你所要求的数的最大范围的1/9,用于存储相应的素数。

2.       5开始判断某个奇数是否为素数(偶数一定不是素数),如果是则放入数组中。

3.       输出数组中的数,即为所求

2.代码:

#include 

using namespace std;

int isPrime(int *prime,int n)

{

      int num= 2;

      prime[0]=2;

      prime[1]=3;

      for(int i=5;i<=n;i+=2)  //排除所有的偶数,逐个判断某个奇数是否为素数

      {

               bool status= true;

               for(int j=0;prime[j]*prime[j]<=i;j++)   //判断i是否为素数

               {

                         if(i%prime[j]==0)

                         {

                                  status= false;

                                  break;

                         }

               }

               if(status)     //ia素数,则放入数组中

                         prime[num++]=i;

      }

      return num;

}

int main( )

{

      int prime[101];

      int num= isPrime(prime,100);

      for(int i=0;i

               cout<<prime[i]<<endl;

      return 0;

}

这种算法节约了大量的空间。在时间复杂度上也比上面那种小。

但是这种算法也有确定,就是不容易确定某个范围内的所有的素数。

5.改进版筛选法:

      1.解题思路:

           1.对于给点的范围[m,n],以m/pp=2,3,….sqrt(n))开始,每次加上p,那么(m/p+p)就为合数。这就像是从m/p开始的素数筛选法。(此时我们需要判断的是m<=m/p+p<=n这个范围内的数是否为素数)

      2.代码:

#include 

using namespace std;

void isPrime(int m,int n,int *prime)

{

   for(int i=2;i*i<=n;i++)

   {

            int less= m/i;

            less*=i;

            for(int j=less;j<=n;j+=i)

                     if(j>=m&&j!=i)     //i=j可以防止把一些素数判断为合数

                               prime[j-m]=0;

   }

}

int main( )

{

   int m,n;

   cin>>m>>n;  //给定的范围[m,n]

   int *prime= new int[n-m+1];

   for(int i=0;i

            prime[i]=1;

   isPrime(m,n,prime);

   for(int i=0;i

   {

            if(prime[i]==1&&(n+i)!=1)

                     cout<<m+i<<endl;

   }

   cin>>m;

   return 0;

}

 

            这种算法可以让我们快速的求出任意给定的连续区域内的素数,而且也很容易查找该素数的位置。

 

 

以上五种方法适合的情况不同,大家要灵活运用。

 

如果以上有错误,请大家不吝指正。

原创粉丝点击