质数的筛选

问题描述:给定一个整数 N,求出 1~N 之间的所有质数,称为质数的筛选问题。

Eratothenes筛法:任意整数 x 的倍数 2x,3x,...都不是质数。我们从 2 开始,由小到大扫描每个数 x,把它的倍数

2x,3x,...[ N / x]*x 标记为合数。当扫描到一个数时,若它尚未标记,则它不能被 2 ~ x-1 之间的任何数整除,该数就是质数。实际上,小于 x^2 的 x 的倍数在扫描更小的数时就已经被标记过了。因此,对于每个数 x ,我们只需要从 x^2 开始,把 x^2,(x+1)*x,...,[ N / x] * x 标记为合数即可。时间复杂度:O(N*loglogN)。

代码实现:

void primes(int n){
    memset(vis,0,sizeof vis);//合数标记
    for(int i = 2; i <= n; i++){
        if(vis[i]) continue;
        printf("%d\n", i);//i是素数
        for(int j = i; j <= n/i; j++)
            vis[i*j]=1;
    }
}

线性筛法:这个方法主要就是用已知的质数去筛出合数。任意一个合数都可以被质因数分解,那么我们就可以用已知的一个素数去筛选出一个以这个质数为最小质因数的合数。按照这个思想,我们在​​​在生成一个需要标记的合数时,每次只想现有的数中乘上一个质因子,并且让它是这个合数的最小质因子。这相当于让合数的质因子从大到小累积,即让 12 只有 3*2*2一种产生方式。每个合数只会被它的最小质因子筛一次,时间复杂度为 O(N)。

int v[maxn];
int prime[maxn],m;
void primes(int n){
    memset(v, 0, sizeof v);//最小质因子
    m = 0;//质数数量
    for(int i = 2; i <= n; i++){
        if(v[i] == 0){//i是质数
            v[i] = i;
            prime[++m] = i;
        }
        //给当前的数 i 乘上一个质因子
        for(int j = 1; j <= m; j++){
            // i 有比 prime[j] 更小的质因子,或者超出 n 的范围。
            if(prime[j] > v[i] || prime[j] > n / i)
                break;
            // prime[j] 是 i*prime[j] 的最小质因子
            v[i*prime[j]] = prime[j];
        }
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", prime[i]);
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值