求十亿内的素数

前几天同学让我帮他做道题,关于求素数的,十亿两分钟内出结果 。 (编译器 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、付费专栏及课程。

余额充值