写$ ext{O}left( n log{log{n}} ight)$的筛法很长时间了,我却从来没想过它的优化.偶然间看到线性筛法,心想大约是不错的优化,于是便爬去学习下.
首先,$ ext{O}left( n log{log{n}} ight)$的筛法肯定要比$ ext{O}left( n ight)$的慢,虽然在现在的机子上不明显.还是不要将$ ext{O}left( n log{log{n}} ight)$比较靠谱.但是线性筛法有着它自己的用途.
先发个普通筛法
#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]){}这里去除了一些重复筛的可能.如何将所有重复的现象去除呢?
于是我们有了欧拉筛法.
欧拉筛法通过不筛除筛除过的数来将时间复杂度优化到$ ext{O}left( n ight)$,也就是每个合数都筛去一遍.这个时间不会超过$ ext{O}left( n ight)$.加上扫一遍的确是线性的.
废话不说上代码再讲.
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 (精确的)