写$\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 (精确的)
来源:https://www.cnblogs.com/tmzbot/p/4006032.html