短小精悍的線性篩法求素數
阿新 • • 發佈:2019-01-01
輸入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已經不需要了。