1.埃式筛选法
从2开始向后枚举每个数的倍数,将其筛选去除,e.g:(2,3,4........p-1)若这个区间里没有任何一个数的倍数是p,则p一定是质数
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string.h> 5 #include <math.h> 6 #include <algorithm> 7 #include <stack> 8 #include <queue> 9 #include <vector> 10 #include <map> 11 #include <set> 12 #define ll long long 13 const int N=1e6+10; 14 using namespace std; 15 typedef pair<int,int>PII; 16 17 int cnt; 18 bool st[N]; 19 20 void sieve_prime(int n){ 21 for(int i=2;i<=n;++i){ 22 if(!st[i]){ 23 cnt++; 24 for(int j=i+i;j<=n;j+=i) st[j]=true; 25 } 26 } 27 } 28 29 int main(){ 30 ios::sync_with_stdio(false); 31 int n; 32 cin>>n; 33 sieve_prime(n); 34 35 printf("%d\n",cnt); 36 return 0; 37 }
2.欧拉筛(线性筛)
我们利用每个合数的最小质因数来进行筛选,i相当于是倍数,如果i%prime[j]==0,那么prime[j]一定是i*prime[j]这个合数的最小质因数,如果i%prime[j]!=0,那么prime[j]也同样还是这个合数的最小质因数(primep[j]比i的任何一个质因数都小)
2020/7/23日补:我们每次去找合数,都是用它的最小质因子来找的,那么我们要实现这个,就要求要在i%prime[j]=0的时候break,因为prime[j]一定是质数,所以它是i的质因子,那么我们再用i去找后面的合数之时,其最小质因子就会是我i%prime[j]=0,时的这个质数,而不是我们当前所枚举的这个质数.
这儿顺便附上一个:https://www.luogu.com.cn/problemnew/solution/P3383,这儿有更加详细的解释
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <stack> 7 #include <queue> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <unordered_set> 12 #include <unordered_map> 13 #define ll long long 14 #define fi first 15 #define se second 16 #define pb push_back 17 #define me memset 18 const int N = 1e8 + 10; 19 const int M = 1e9 + 7; 20 using namespace std; 21 typedef pair<int,int> PII; 22 typedef pair<long,long> PLL; 23 int n,q,k; 24 int prime[N],cnt; 25 bool st[N]; 26 27 void get_prime(int n){ 28 for(int i=2;i<=n;++i){ 29 if(!st[i]) prime[cnt++]=i; 30 for(int j=0;j<cnt && prime[j]<=n/i;++j){ 31 st[i*prime[j]]=true; //一定能保证prime[j]是i*prime[j]的因数 32 if(i%prime[j]==0) break; 33 } 34 } 35 } 36 37 int main() { 38 ios::sync_with_stdio(false); 39 cin>>n>>q; 40 get_prime(n); 41 while(q--){ 42 cin>>k; 43 printf("%d\n",prime[k-1]); 44 } 45 return 0; 46 }