线性筛法(欧拉筛法)求素数

写$\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 (精确的)
posted @ 2014-10-04 15:24 zball 阅读(...) 评论(...) 编辑 收藏