求素数

/*
题目描述:求出N内的所有素数,把他们存储到数组sushu[MAX] 中,并返回素数的个数。

算法描述:在下面的程序中我分别使用了常规方法和新方法求素数表,结果新方法所用时间远小于常规方法。
新方法的思路其实不新,只是利用了一个小技巧:一个正整数如果不能被所有不大于它的平方根的素数整除,则它一定是素数。我在判断正整数i是否为素数时,不是让它去整除每一个不大于它的平方根的正整数,而是让它去整除已经得到的素数表中的素数(此时素数表中的素数比i要小),这样就大大地减少了运算量。

注意:另外还有一种类似桶式排序的方法,是把所要分析的正整数作为布尔数组p[N]的下标,
先给布尔数组p[N]赋初值为true。从i=2开始分析,若p[i]==true,则i的所有倍数j=n*i均为非素数,将以j为下标的元素p[j]==false;直到i==N/2结束分析。
遍历布尔数组p[N],若若p[i]==true,则表示i为素数,将其存入素数表。
这种方法速度也很快,但它需要设置一个长度为N的布尔数组p[N],当N很大时,会占用过多内存空间,导致程序不能执行。
*/
#include <iostream>
#include <math.h>
#include <time.h>
using namespace std;

long Sushu_1(long a[], long n);
long Sushu_2(long a[], long n);
long Sushu_3(long a[], long n);

int main()
{
      const long MAX = 150000; //预计素数总的个数
      const long N = 2000000; //被分析的数的最大值,若执行Sushu_3(),N不能超过1000000
      //
      time_t startTime_1;
    time_t endTime_1;
      time(&startTime_1);

      long sushu_1[MAX] = {0};
      long top_1 = Sushu_1(sushu_1, N);//使用常规方法求素数表
      cout << "top_1 = " << top_1 << endl;

      time(&endTime_1);
      cout << "time_1 = " << difftime(endTime_1, startTime_1) << endl;
      
      time_t startTime_2;
    time_t endTime_2;
      time(&startTime_2);

      long sushu_2[MAX] = {0};
      long top_2 = Sushu_2(sushu_2, N); //使用新方法求素数表
      cout << "top_2 = " << top_2 << endl;

      time(&endTime_2);
      cout << "time_2 = " << difftime(endTime_2, startTime_2) << endl;
      
      //time_t startTime_3;
//    time_t endTime_3;
//      time(&startTime_3);
//
//      long sushu_3[MAX] = {0};
//      long top_3 = Sushu_3(sushu_3, N); //使用桶式排序的方法求素数表
//      cout << "top_3 = " << top_3 << endl;
//
//      time(&endTime_3);
//      cout << "time_3 = " << difftime(endTime_3, startTime_3) << endl;
      
      getchar();
      return 0;
}

long Sushu_1(long a[], long n)//使用常规方法求素数表
{
      a[0] = 2;
      long top = 1;
      for (long i=3; i<=n; i+=2)
      {
            long q = (long)sqrt(i);
            bool flag = true;
            for (long j=2; j<=q; j++)
            {
                  if (i%j == 0)
                  {
                        flag = false;
                        break;
                  }
            }
            if (flag)
                  a[top++] = i;
      }
      
      return top;
}

long Sushu_2(long a[], long n)//使用新方法求素数表
{
      a[0] = 2;
      long top = 1;
      for (long i=3; i<=n; i+=2)
      {
            long q = (long)sqrt(i);
            bool flag = true;
            for (long j=0; a[j]<=q && j<top; j++)
            {
                  if (i%a[j] == 0)
                  {
                        flag = false;
                        break;
                  }
            }
            if (flag)
                  a[top++] = i;
      }
      
      return top;
}

long Sushu_3(long a[], long n) //使用桶式排序的方法求素数表,n不能太大
{
      bool *p = new bool[n+1];
      for (long i=0; i<=n; i++)
            p[i] = true;
            
      long m = n / 2;
      for (long i=2; i<=m; i++)
    {
        if (p[i])//若i为素数,则i的整数倍必为非素数
        {
            for (long j=2*i; j<=n; j+=i)
                p[j] = false;
            }
    }
    
    long top = 0;
      for (long i=2; i<=n; i++)//累积素数
            if (p[i])
                  a[top++] = i;
      delete []p;
                  
      return top;
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值