P3383 【模板】线性筛素数
链接:P3383
---------------------------------------------
这道题考的是一个线性筛,主要有两种:埃氏筛和欧拉筛
先说埃氏筛,埃氏筛很简单。只要检查每一个数。如果他是没有被标记,就证明他是一个质数。这样我们就需要把他的每一个数标记为合数,然后重复
极为简单
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 long int a[10000000]; 4 int main() 5 { 6 int n; 7 a[1]=1; 8 cin >>n; 9 for(int i=2;i<=n;++i) 10 { 11 if(a[i]==0) 12 { 13 int j=2; 14 while(i*j<=n) 15 { 16 a[i*j]=1; 17 j++; 18 } 19 } 20 } 21 int num; 22 cin>>num; 23 for(int j=1;j<=num;++j) 24 { 25 int que; 26 cin>>que; 27 if(a[que]==0) 28 cout<<"Yes\n"; 29 else 30 cout<<"No\n"; 31 } 32 return 0; 33 }
-------------------------------------------
下面就是欧拉筛了。欧拉筛大体一样。主要是如果一个点没有被标记,就把他加入一个质数数组中。
然后遍历这个数组,用这个点的编号乘以目前每一个质数。并标记
--------------------------------------------
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int n,m; 5 int prime[10000001]; 6 int flag[10000001]; 7 int num; 8 int now; 9 int main(){ 10 scanf("%d%d",&n,&m); 11 flag[1]=1; 12 for(int i=2;i<=n;++i){ 13 if(!flag[i]) { 14 prime[++num]=i;; 15 } 16 for(int j=1;j<=num&&i*prime[j]<=n;j++){ 17 flag[i*prime[j]]=1; 18 if(i%prime[j]==0) break;//关键 19 // 20 } 21 } 22 23 for(int ii=1;ii<=m;++ii){ 24 cin>>now; 25 if(!flag[now]) 26 cout<<"Yes"<<endl; 27 else 28 cout<<"No"<<endl; 29 } 30 return 0; 31 }
--------------------------------------------
建议下特别的关键
欧拉筛保证线形的关键就是每个点只被更新一次(埃氏筛不能)
做到这点的关键就是保证每个数只被最小的质因子更新。
看一看这一句,我们假设没有,因为我们已经知道了prime[j]是i的因子,
那么我们假设prime[j]*k=i,然后我们再更新 prime[j+1]的时候,就等于是更新了prime[j]*k*prime[j+1];
然而我们要做到被最小的,很明显prime[j+1]>prime[j],这样就不是用最小的了,会发生重复。
这样就不是线性了(加上就是同理)