其他分享
首页 > 其他分享> > 集训第二天关于素筛的总结

集训第二天关于素筛的总结

作者:互联网

素筛

怎么说呢,我对筛也不是算很了解,但还是发表一下我对素筛的理解吧。

一.埃氏筛

我认为,埃氏筛比较好理解,也容易写出来,但若数据大于了1e7,此时埃氏筛就不好跑出结果,所以埃氏筛再简单的同时也是有代价的。

埃氏筛的原理:我们知道一个合数必定能分解为两个数的积,如4能拆分为2*2,8能拆分为2*4与8*1,所以我们就可以用这个原理来达到埃氏筛的目的。

 

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 int N = 1005;
 4 int main()
 5 {
 6     int max;
 7     scanf("%d",&max);
 8     int prime[N] = {0};//存素数
 9     bool on[N];//是否为素数 
10     int cnt = 0;//素数的个数
11     memset(on,true,sizeof(on));//初始化全为素数
12     on[0] = on[1] = false;//0和1不为素数;
13     for(int i = 2;i<=max;i++)
14     {
15         if(on[i])
16         {
17             prime[++cnt] = i;
18             for(int j = i+i;j<=max;j+=i)
19             {
20                 on[j] = false;
21             }
22         }
23     }
24     printf("%d\n",cnt);
25     return 0;
26 }

二.欧拉筛

哎,它来了,我认为欧拉筛是筛中最难理解的了,因为他有些关键的东西,比较晦涩难懂,想想昨天下午我用可以下午都没将他搞懂(突然觉得自己好没用),但有一说一,欧拉筛还是比较好用的:因为欧拉筛可以保证合数只被最大质因数筛掉,可以有效减少合数被重复筛去的情况,从而可以大幅减小跑程序的时间。

核心思路:当i%prime[j]==0时,应该break掉,我感觉是为了防止一个数被重复筛去。

下面上最关键的代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <iostream>
 5 #include <string>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <set>
 9 #include <map>
10 using namespace std;
11 const int N = 100000100;
12 bool on[N]; //判断下标是否为素数
13 int prime[N];//存放素数的
14 int n, cnt = 0;
15 
16 int main() {
17     cin >> n;
18     memset(on, true, sizeof(on));
19     on[0] = on[1] = false;//0,1不为素数
20     for(int i = 2; i <= n; i++) {
21         if(on[i]) prime[++cnt] = i;//为真
22         for(int j = 1; j <= cnt && prime[j] * i <= n; j++) {
23             on[prime[j] * i] = false;
24             if(i % prime[j] == 0) break;//保证每个合数都只被它的最大公约数筛 
25                 
26         }
27     }//先标记再筛
28     int tot = 0;
29     for(int i = 0; i <= n; i++) {
30         if(on[i]) tot++;
31 
32     }
33     cout << tot;
34     return 0;
35 }

感觉我这次对筛的总结很水,希望多多包涵,因为我也有点忙碌地把他写完。

下面附上风景照一张。

标签:总结,prime,埃氏,int,素数,第二天,include,集训,欧拉
来源: https://www.cnblogs.com/zjdeboke/p/14290038.html