集训第二天关于素筛的总结
作者:互联网
素筛
怎么说呢,我对筛也不是算很了解,但还是发表一下我对素筛的理解吧。
一.埃氏筛
我认为,埃氏筛比较好理解,也容易写出来,但若数据大于了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