1. 程式人生 > >短小精悍的線性篩法求素數

短小精悍的線性篩法求素數

輸入n,求n以內的所有素數

演算法用兩個陣列儲存資料:
一個是prime[],儲存n以內所有的素數,其index為pi,初值為0
一個是is_prime[i],表示自然數i(i<=n)是不是質數。

void genPrime() 
{ 
        memset(isPrime,1,sizeof(isPrime)); 
        for(long i = 2 ; i < N ; i++)        
        {             
            if(isPrime[i]){ 
                prime[num_prime ++]=i; 
            }                      
            //關鍵處1         
            for(long j = 0 ; j < num_prime && i * prime[j] <  N ; j ++) 
            {                
                isPrime[i * prime[j]] = 0;   
                if( !(i % prime[j] ) )  //關鍵處2                   
                    break;            
            }         
        }   
} 

第一層遍歷2到N之間的所有自然數i,看看它是不是質數,如果是,則把i放進prime陣列中。

第二層迴圈是對所有未來的數進行篩選。對於當前正在處理的i,顯然它乘以任何一個已經找到的素數的結果肯定是合數,它們將會被剔除。

整個演算法最核心的一句是第13行:當i可以被某個已經找到的質數整除的時候,迴圈退出,不再進行剔除工作。

這樣做的原因是:當prime[j]是i的因子的時候,設i = prime[j]*k,

       首先,我們可以肯定的說,prime[j]是i的最小質因數,這是因為第二層迴圈是從小到大遍歷素數的;

       其次,我們可以肯定的說,i已經無需再去剔除prime[j']*i (j'>j) 形式的合數了,這是因為,

                                          prime[j']*i可以寫成prime[j'] *(prime[j]*k) = prime[j]*(prime[j']*k),也就是說所有的prime[j']*i將會被將來的某個i'=prime[j']*k剔除掉,當前的i已經不需要了。