C语言-常规筛、埃氏筛、欧拉筛

素数定义

除了自身与1之外没有其他因数

例子

输入一个数字n,求出n以内包括n的所有素数

  1. 常规筛
    时间复杂度O(n*sqrt(n))
#include <stdio.h>
int isPrime(int num){
    for(int i=2; i*i<=num; i++)
        if(num%i==0){return 0; break;}
    return 1;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=2; i<=n; i++)
        if(isPrime(i))  printf("%d\n",i);
    return 0;
}
  1. 埃氏筛
    思路:
    时间复杂度O(nloglogn),首先,2是公认最小的质数,所以,先把所有2的倍数去掉;然后剩下的那些大于2的数里面,最小的是3,所以3也是质数;然后把所有3的倍数都去掉,剩下的那些大于3的数里面,最小的是5,所以5也是质数…
    上述过程不断重复,就可以把某个范围内的合数全都除去(就像被筛子筛掉一样),剩下的就是质数了。
#include <stdio.h>
int main(){
    int n;
    scanf("%d",&n);
    int isPrime[n+1];
    for(int i=0; i<n+1; i++)    isPrime[i]=1;
    isPrime[0]=isPrime[1]=0;
    for(int i=2; i<=n; i++){
        if(isPrime[i]){
            printf("%d\n",i);
            for(int j=2; i*j<=n; j++)   isPrime[i*j]=0;
        }
    }
    return 0;
}
  1. 欧拉筛
    思路:
    时间复杂度为O(n)。与埃氏筛相比,不会对已经被标记过的合数再进行重复筛,故效率更高。欧拉筛保证合数仅被该合数的最小值因数筛去仅一次。
#include<stdio.h>
#include<stdbool.h>
int main(void){
    int n,count=0;
    scanf("%d",&n);
    bool number[n+1];
    int prime[n+1];
    memset(number,true,sizeof(number));
    for(int i=2;i<=n;i++){
        if(number[i])   prime[count++]=i;
        for(int j=0;j<count&&prime[j]*i<=n;j++){
            number[prime[j]*i]=false;
            if(i%prime[j]==0)	break;
        }
    }
    for(int i=2;i<n+1;i++)
        if(number[i]==true) printf("%d\n",i);
    return 0;
}

关键在于理解第13行的if(i%prime[j]==0) break;,该行保证了每一个合数只被它的最小质因数筛一次。
例如当i%prime[j]==0时,则i*prime[j+1]一定是prime[j]的整数倍,因为i可以整除prime[j],并且i*prime[j+1]/prime[j]>i所以在当前i中,i*prime[j+1]还不能被筛,因为当前的i无法使得i*prime[j+1]/prime[j]等于i*prime[j+1]的最小质因数。举个例子:当i=8prime数组中有{2,3,5,7},此时计算i*prime[j],0<=j<4,结果为{16,24,40,56},此时16除以8等于2,2是16的最小质因数,所以16被筛去;但此时24除以8等于3,3不是24的最小质因数,所以此时24不能被筛去,因为24应该被2筛去,而24除以2等于12,所以24应该在i=12的时候被筛去,40与56同理。综上,当if(i%prime[j]==0)时,跳出循环。
打印出当n=100时的运行过程帮助理解:

4被2筛去,此时i=2
6被2筛去,此时i=3
9被3筛去,此时i=3
8被2筛去,此时i=4
10被2筛去,此时i=5
15被3筛去,此时i=5
25被5筛去,此时i=5
12被2筛去,此时i=6
14被2筛去,此时i=7
21被3筛去,此时i=7
35被5筛去,此时i=7
49被7筛去,此时i=7
16被2筛去,此时i=8
18被2筛去,此时i=9
27被3筛去,此时i=9
20被2筛去,此时i=10
22被2筛去,此时i=11
33被3筛去,此时i=11
55被5筛去,此时i=11
77被7筛去,此时i=11
24被2筛去,此时i=12
26被2筛去,此时i=13
39被3筛去,此时i=13
65被5筛去,此时i=13
91被7筛去,此时i=13
28被2筛去,此时i=14
30被2筛去,此时i=15
45被3筛去,此时i=15
32被2筛去,此时i=16
34被2筛去,此时i=17
51被3筛去,此时i=17
85被5筛去,此时i=17
36被2筛去,此时i=18
38被2筛去,此时i=19
57被3筛去,此时i=19
95被5筛去,此时i=19
40被2筛去,此时i=20
42被2筛去,此时i=21
63被3筛去,此时i=21
44被2筛去,此时i=22
46被2筛去,此时i=23
69被3筛去,此时i=23
48被2筛去,此时i=24
50被2筛去,此时i=25
75被3筛去,此时i=25
52被2筛去,此时i=26
54被2筛去,此时i=27
81被3筛去,此时i=27
56被2筛去,此时i=28
58被2筛去,此时i=29
87被3筛去,此时i=29
60被2筛去,此时i=30
62被2筛去,此时i=31
93被3筛去,此时i=31
64被2筛去,此时i=32
66被2筛去,此时i=33
99被3筛去,此时i=33
68被2筛去,此时i=34
70被2筛去,此时i=35
72被2筛去,此时i=36
74被2筛去,此时i=37
76被2筛去,此时i=38
78被2筛去,此时i=39
80被2筛去,此时i=40
82被2筛去,此时i=41
84被2筛去,此时i=42
86被2筛去,此时i=43
88被2筛去,此时i=44
90被2筛去,此时i=45
92被2筛去,此时i=46
94被2筛去,此时i=47
96被2筛去,此时i=48
98被2筛去,此时i=49
100被2筛去,此时i=50

参考

https://blog.dotcpp.com/a/60294

  • 16
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值