寫$\text{O}\left( n \log{\log{n}}\right)$的篩法很長時間了,我卻從來沒想過它的優化.偶然間看到線性篩法,心想大約是不錯的優化,於是便爬去學習下.
首先,$\text{O}\left( n \log{\log{n}}\right)$的篩法肯定要比$\text{O}\left( n\right)$的慢,雖然在現在的機子上不明顯.還是不要將$\text{O}\left( n \log{\log{n}}\right)$比較靠譜.但是線性篩法有着它自己的用途.
先發個普通篩法
#include <cmath> bool sieve[1000000]; int prime[1000000],ps,temp,temp2,temp3; void normal_sieve(int n){ temp=sqrt(n)+10; for(i=2;i<temp;++i){ if(!sieve[i]){ prime[ps++]=i; temp2=(n/i)+1; temp3=i; for(j=2;j<=temp2;++j){ temp3+=i; sieve[temp3]=true; } } } for(;i<=n;++i){ if(!sieve[i]){ prime[ps++]=i; } } }//包含了幾乎所有有用功能的普通篩法
(orz神犇WJZ先)
如何把篩法優化到線性呢?
注意到在普通篩法中我們的優化if(!sieve[i]){}這里去除了一些重復篩的可能.如何將所有重復的現象去除呢?
於是我們有了歐拉篩法.
歐拉篩法通過不篩除篩除過的數來將時間復雜度優化到$\text{O}\left( n\right)$,也就是每個合數都篩去一遍.這個時間不會超過$\text{O}\left( n\right)$.加上掃一遍的確是線性的.
廢話不說上代碼再講.
bool IsPrime[10000001]; int Pri[2000001],PriN; int FindPrime ( int MaxN ) { for( int i = 2 ; i <= MaxN ; ++i ){ if( IsPrime[ i ] ) Pri[ PriN++ ]=i; //將這句話放在下面的循環前以保證PriN和Pri值的完整性 for(int j=0;j<PriN;++j){ if( i*Pri[ j ] > MaxN ) break; //當過大了就跳出 IsPrime[ i * Pri[ j ] ] = 0; //篩去素數 if( i % Pri[ j ] == 0 ) break; //這里是關鍵,如果i是一個合數(這當然是允許的)而且i mod prime[j] = 0 //那么跳出,因為i*prime[ (- over -)j ]一定已經被篩去了,被一個素因子比i小的數 } } }
對比:(普通篩法在下,經過優化)
200:
Euler : 46 0.00000000
Eratosthenes : 46 0.00000000
239:
Euler : 51 0.00000000
Eratosthenes : 52 0.00000000
286:
Euler : 61 0.00000000
Eratosthenes : 61 0.00000000
343:
Euler : 68 0.00000000
Eratosthenes : 68 0.00000000
411:
Euler : 80 0.00000000
Eratosthenes : 80 0.00000000
493:
Euler : 94 0.00000000
Eratosthenes : 94 0.00000000
591:
Euler : 107 0.00000000
Eratosthenes : 107 0.00000000
709:
Euler : 126 0.00000000
Eratosthenes : 127 0.00000000
850:
Euler : 146 0.00000000
Eratosthenes : 146 0.00000000
1019:
Euler : 170 0.00000000
Eratosthenes : 171 0.00000000
1222:
Euler : 199 0.00000000
Eratosthenes : 199 0.00000000
1466:
Euler : 232 0.00000000
Eratosthenes : 232 0.00000000
1759:
Euler : 273 0.00000000
Eratosthenes : 274 0.00000000
2110:
Euler : 317 0.00000000
Eratosthenes : 317 0.00000000
2531:
Euler : 369 0.00000000
Eratosthenes : 370 0.00000000
3037:
Euler : 434 0.00000000
Eratosthenes : 435 0.00000000
3644:
Euler : 510 0.00000000
Eratosthenes : 510 0.00000000
4372:
Euler : 596 0.00000000
Eratosthenes : 596 0.00000000
5246:
Euler : 697 0.00000000
Eratosthenes : 697 0.00000000
6295:
Euler : 818 0.00000000
Eratosthenes : 818 0.00000000
7553:
Euler : 958 0.00000000
Eratosthenes : 958 0.00000000
9063:
Euler : 1126 0.00000000
Eratosthenes : 1126 0.00000000
10875:
Euler : 1322 0.00000000
Eratosthenes : 1322 0.00000000
13049:
Euler : 1554 0.00000000
Eratosthenes : 1555 0.00000000
15658:
Euler : 1826 0.00000000
Eratosthenes : 1826 0.00000000
18789:
Euler : 2143 0.00000000
Eratosthenes : 2143 0.00000000
22546:
Euler : 2520 0.00000000
Eratosthenes : 2520 0.00000000
27055:
Euler : 2965 0.00000000
Eratosthenes : 2965 0.00000000
32465:
Euler : 3483 0.00000000
Eratosthenes : 3483 0.00000000
38957:
Euler : 4103 0.00000000
Eratosthenes : 4103 0.00000000
46748:
Euler : 4830 0.00000000
Eratosthenes : 4830 0.00000000
56097:
Euler : 5691 0.00000000
Eratosthenes : 5691 0.00000000
67316:
Euler : 6706 0.00000000
Eratosthenes : 6706 0.00000000
80779:
Euler : 7905 0.00000000
Eratosthenes : 7906 0.00000000
96934:
Euler : 9330 0.00000000
Eratosthenes : 9330 0.00000000
116320:
Euler : 10988 0.00000000
Eratosthenes : 10988 0.00000000
139583:
Euler : 12972 0.00000000
Eratosthenes : 12972 0.00000000
167499:
Euler : 15302 0.00000000
Eratosthenes : 15302 0.00000000
200998:
Euler : 18061 0.00000000
Eratosthenes : 18061 0.00000000
241197:
Euler : 21317 0.00000000
Eratosthenes : 21317 0.01600000
289436:
Euler : 25181 0.00000000
Eratosthenes : 25181 0.00000000
347323:
Euler : 29767 0.00000000
Eratosthenes : 29767 0.00000000
416787:
Euler : 35135 0.00000000
Eratosthenes : 35135 0.00000000
500144:
Euler : 41548 0.00000000
Eratosthenes : 41548 0.01600000
600172:
Euler : 49108 0.01500000
Eratosthenes : 49108 0.00000000
720206:
Euler : 58044 0.00000000
Eratosthenes : 58044 0.01600000
864247:
Euler : 68661 0.01500000
Eratosthenes : 68661 0.01600000
1037096:
Euler : 81210 0.01600000
Eratosthenes : 81210 0.01500000
1244515:
Euler : 96065 0.01600000
Eratosthenes : 96065 0.01500000
1493417:
Euler : 113703 0.03100000
Eratosthenes : 113703 0.01600000
1792100:
Euler : 134513 0.03200000
Eratosthenes : 134513 0.03200000
2150519:
Euler : 159280 0.03200000
Eratosthenes : 159280 0.03200000
2580622:
Euler : 188550 0.03200000
Eratosthenes : 188550 0.03100000
3096746:
Euler : 223297 0.04700000
Eratosthenes : 223297 0.04600000
3716095:
Euler : 264452 0.06300000
Eratosthenes : 264452 0.06300000
4459313:
Euler : 313275 0.07800000
Eratosthenes : 313275 0.07800000
5351175:
Euler : 371197 0.09400000
Eratosthenes : 371197 0.10900000
6421409:
Euler : 439770 0.09400000
Eratosthenes : 439770 0.14000000
7705690:
Euler : 521256 0.12500000
Eratosthenes : 521256 0.15600000
9246827:
Euler : 617847 0.15600000
Eratosthenes : 617847 0.20300000
11096192:
Euler : 732467 0.18700000
Eratosthenes : 732467 0.23400000
13315430:
Euler : 868429 0.20300000
Eratosthenes : 868429 0.29700000
15978515:
Euler : 1029823 0.25000000
Eratosthenes : 1029823 0.36000000
19174217:
Euler : 1221415 0.29700000
Eratosthenes : 1221415 0.45300000
23009060:
Euler : 1448793 0.37500000
Eratosthenes : 1448793 0.54700000
27610871:
Euler : 1718770 0.43800000
Eratosthenes : 1718770 0.67200000
33133045:
Euler : 2039320 0.53100000
Eratosthenes : 2039320 0.78100000
39759653:
Euler : 2420000 0.64100000
Eratosthenes : 2420001 0.96800000
47711583:
Euler : 2871837 0.79700000
Eratosthenes : 2871837 1.17200000
57253899:
Euler : 3408686 0.95300000
Eratosthenes : 3408686 1.42200000
68704678:
Euler : 4046322 1.14000000
Eratosthenes : 4046322 1.71900000
82445613:
Euler : 4803832 1.39100000
Eratosthenes : 4803832 2.07800000
98934735:
Euler : 5703624 1.67200000
Eratosthenes : 5703624 2.53100000
但是題目一般來說不會出這么喪心病狂的數據
晚些發放更大的測試數據
鏈接: http://pan.baidu.com/s/1eQCcD8Y 密碼: 1ck6
鏈接: http://pan.baidu.com/s/1kTh0qov 密碼: jcya (精確的)