简单素数筛选法介绍(数论初步) By ACReaper

我们介绍一下素数筛选法。

给你1---n的连续整数,把这些数中的素数筛选出来,用到的思路很简单。其原理基于,对于数p如果p的倍数存在与表中,则这个p的倍数一定不是素数,我们可以把它删除,但是这样删除的干净吗?这是个好问题,我们可以从小到大,从2开始枚举,至于1为什么不行,想想也应该能明白吧,然后可以用数学归纳法证明,当结束时,整张表必然是素数表,因为除了1和它本身,没有其它的数能整除。


先写出无改进版本的:

#include <stdio.h>
#define MAXN 10000000
int vis[MAXN];
int n;
int main(){
	while(scanf("%d",&n) != EOF){
		for(int i = 2; i <= n; i++){
			for(int j = 2 * i; j <= n; j += i)
				vis[j] = 1;
		}
		for(int i = 2; i <=n; i++ ){
			if(!vis[i]){
				printf("%3d ",i);
			}
			
		}
	
	}
	return 0;
}

那么这个算法的效率是多少呢?O(n  * n)?当然不是了。可以这么算循环循环总的次数 小于 n/2 + n/3 + n /4 + .... + n / n 这个值,学过高等数学的数列求和的应该会把,= O(n * log n)。


下面来改进代码·,我们可以很容易观察到,上面存在重复的运算,因为对于3,9,他们也有相同的公倍数,也就是所对于选中的i,在i之前的2 --- I - 1 的倍数早就被删处了,不用在重复删除了,所以j = I * i。


int m = sqrt(n + 0.5); 
int c = 0;
memset(vis,0,sizeof(vis));
for(int i = 2; i <= m; i++){
	if(!vis[i]){
		prime[c++] = i;
		for(int j = i * i; j <=n; j+= i)
			vis[j] = 1; 
	} 
	
}


顺便说下素数定理:

pai(x)等价于 x / ln (x)

posted @ 2013-04-20 17:39  算法黑魔王  阅读(302)  评论(0编辑  收藏  举报