素数筛法

来源:互联网 发布:ssd优化 编辑:程序博客网 时间:2024/06/13 11:20

注:代码很长,不要害怕,不难的,核心代码只有几行,贴上完整代码是为了大家测试方便。

首先要明白的是 素数的倍数一定不是素数。


筛法1

在0-n之间的数字筛法的基本思想:

首先假设0-n全部都是素数

然后从2开始遍历到sqrt(n),

如果该数是素数,那么在区间 [ 这个数的平方, n ] 上将是这个数字的倍数的数标记为非素数。

如果该数是合数,重复上一步。

证明略。

 

时间复杂度O( N log ( N ) )

#include <cstdio> #include <iostream>#include <map>#include <set>#include <vector>#include <cmath>#include <string>#include <cstring>#include <algorithm>#define LL long long#define MAXN 100000using namespace std;/*素数筛法 */int valid[MAXN+1];int prime[MAXN+1];int tot;void getPrime(){memset(valid, 0, sizeof(valid));tot = 0;for(int i = 2; i <= sqrt(MAXN); i++){if(valid[i]) continue;for(int j = i*i; j <= MAXN; j+=i){valid[j] = 1;}}for(int i = 2; i <= MAXN; i++){if(!valid[i]) prime[tot++] = i;}} // testint main(){getPrime();for(int i = 0; i < tot; i++){printf("%d ",prime[i]);}return 0;}

筛法2

在0-n之间的数字筛法的基本思想:

首先假设0-n全部都是素数

然后从2开始遍历到n,我们假设当前遍历位置为i

如果该数是素数,记录该素。

不论该数是不是素数,我们都遍历已经存储的素数,并且将该素数的i倍标记为不是素数。

但是如果i是当前遍历的素数的倍数,那么就结束素数的遍历。

证明略。


时间复杂度O( N )

#include <cstdio> #include <iostream>#include <map>#include <set>#include <vector>#include <cmath>#include <string>#include <cstring>#include <algorithm>#define LL long long#define MAXN 100000using namespace std;/*素数筛法 */int valid[MAXN+1];int prime[MAXN+1];int tot;void getPrime(){memset(valid, 0, sizeof(valid));tot = 0;for(int i = 2; i <= MAXN; i++){if(!valid[i]){prime[tot++] = i;}for(int j = 0; (j < tot) && (i*prime[j] <= MAXN); j++){valid[i*prime[j]] = 1;if(i%prime[j] == 0) break;}}} // testint main(){getPrime();for(int i = 0; i < tot; i++){printf("%d ",prime[i]);}return 0;}



1 0
原创粉丝点击