求十亿内的素数

本文介绍了一种通过预计算小范围素数并利用这些素数来加速大范围素数筛选的方法,采用BigMap算法实现,并提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前几天同学让我帮他做道题,关于求素数的,十亿两分钟内出结果 。 (编译器 mingw-g++)

最开始是用的最常见的欧几里得筛选法

 

bool IsPrime(long x)
{
    
int s=(int)sqrt(x);
    
for(int i=3;i<=s;i+=2)
    {
        
if(x%i==0)
            
return false;
    }
    
return true;
}

 

        也就是一个双重循环,外层把数从1到n 跑一遍,只测试奇数。时间复杂度大约是O(N3/2).后来发现速度是相当的慢,这种算法效率无法达到要求。

        改用BigMap算法。这里我先把1到10万内的素数求出来,放在一个数组里面(方法还是用的上面那种,这里对效率影响不是很大。总共用时在1秒以内)。然后以此为基数再判定后面的数。

      

bool BigmapPrime(int a,long x[])
{
    
for(int i=1;x[i]*x[i]<=a;i++)
    {
        
if(a%x[i]==0)
            
return false;
    }
    
return true;
}

 

 

    这里x[ ]里面是1到10万的素数,x[0]=2可以不用测。时间复杂度约为O(10000N).

    这个时候求1千万内的素数大概用时6.22秒,2千万 15.22秒,3千万 25.95秒。

    后来测十亿时,半个小时没出结果,我把素数输出到一个文件里面,大小约320M。我看了下,这时才走到6亿9千万。

     最后,考虑到函数入栈出栈的时间,我把BigMap内联了,这里是全部的代码。

 

#include <iostream>
#include 
<fstream>
#include 
<math.h>
#include 
<time.h>

using namespace std;

bool IsPrime(long x);
void MakeBasePrime(long*);

const int BASE=9592;
//9592 is the number of the primes in 1 to 100000

int main()
{
    clock_t start,finish;
    
long range;
    
long count=0;
    
long baseprime[BASE];

    cout
<<"Input the max number:";
    cin
>>range;

    start
=clock();
    MakeBasePrime(baseprime);

    ofstream 
out("prime.txt");
    
for(int i=100001;i<=range;i+=2)
    {
        
if(i%3==0 || i%5==0 || i%7==0 || i%11==0 || i%13==0 || i%17==0 || i%19==0)
            
continue;
        
bool flag=true;

        
for(int j=8;baseprime[j]*baseprime[j]<=i;j++)
        {
            
if(i%baseprime[j]==0)
            {
                flag
=false;
                
break;
            }
        }

        
if(flag)
        {
            
out<<i<<" ";
            count
++;
            
if(count%10==0)
                
out<<endl;
        }
    }

    cout
<<" The least prime count = "<<count;

    finish
=clock();
    cout
<<" The whole time lapse is "<<(double)(finish-start)/CLOCKS_PER_SEC;
    cin.
get();
    
return 0;
}


bool IsPrime(long x)
{
    
int s=(int)sqrt(x);
    
for(int i=3;i<=s;i+=2)
    {
        
if(x%i==0)
            
return false;
    }
    
return true;
}

void MakeBasePrime(long x[])
{
    
int k=1;
    x[
0]=2;
    ofstream 
out("baseprime.txt");
    
out<<x[0]<<" ";
    
for(int i=3;i<100000;i+=2)
    {
        
if(IsPrime(i))
        {
            x[k]
=i;
            
out<<x[k]<<" ";
            k
++;
            
if(k%10==0)
                
out<<endl;
        }
    }
    cout
<<" The count of prime range 1 to 100000 = "<<k<<endl;
}

       在用BigMap判定素数前,先用if语句测试前几个。因为在多次实验中这样时间有一定的减少,但如果if语句再多测几个数,速度会变慢,具体原因还不清楚,可能是编译器优化的原因。

       这里是几组测出来的时间:

        1千万                5.828 s
        2千万              14.313 s
        3千万              24.109 s
        1亿                125.094 s

如果不输出到文件,时间每1千万大概能减少1秒。这里看来十亿估计也在半小时左右。

如果有高人能有更好的解法,欢迎赐教。

                                                                                                              
 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值