筛素数
素数是一个非常神奇的东西,它的因子只有它自己和1,那么问题来了,怎么在一个有限的区间内打印出所有的素数呢?咱们就先来解决这一个基本的问题。
我们可以针对“它的因子只有它自己和1”这个特殊点来进行筛查。先判断区间内每一个数是否都是素数,就可以遍历整个区间的每一个整数,看看这个数除以除1和自己本身之外,是否还有别的因子,有的话就不是喽,然后再把筛到的素数打印就行喽:
//判断素数 #include <cstdio> //c = a * b #include <cmath> #define N 10005 using namespace std; //min(a , b) <= sqrt (c) bool mindiv[N];//一个数字的最小素因子 int prime[N]; int tot; bool judge(int x)//判断素数 { for(int i = 2 ; i <= sqrt(x) ; i ++) { if(x % i == 0) return false; } return true; } //Miller Rabin int main() { bool not_prime[10005]; int n; scanf("%d",&n); for(int i = 2 ; i <= n ; i ++) { if(judge(i)) printf("%d ",i); } //筛n以内的素数,打印出来,但复杂度有点大O(n) puts(" "); for(int i = 2 ; i<= n ; i ++) { if(! not_prime[i]) { printf("%d " ,i); for(int j = 2 ; j * i <= n ; j ++) { not_prime[j * i] = true; } } }//复杂度为nlogn,埃式拆法 //n/2 + n/3 + n/5 +...... puts(" "); for(int i = 2 ; i <= n ; i ++) { if(! mindiv[i]) { mindiv[i] = i; prime[tot ++] = i; printf("%d ", i); } for(int j = 0 ; prime[j] * i <= n ; j ++) { mindiv[prime[j] * i] = prime[j]; // prime[j] <= mindiv[i] //printf("# %d = %d * %d\n",prime[j] * i , i ,prime[j]); //输出判断i何时被筛掉 if(prime[j] == mindiv[i]) break; } } //为何是线性 // 10 2 3 5 7 return 0; }
第一个是正常枚举筛。
第二个和第三个是埃式筛法和线性筛法。