筛素数

素数是一个非常神奇的东西,它的因子只有它自己和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; 
} 

 

第一个是正常枚举筛。

 

第二个和第三个是埃式筛法和线性筛法。

posted @ 2018-02-09 11:11  Zhoier  阅读(218)  评论(0编辑  收藏  举报