原題 https://www.luogu.org/problemnew/show/P1865ios
原本get到了一個很好的判斷素數的方法ui
O(玄學常數)https://www.luogu.org/blog/nopartyfoucaodong/solution-p3383 (個人luogu博客 嘻嘻)spa
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; int n,m; bool su(int a){ if(a==1) return 0; if(a==2||a==3) return 1; if(a%6!=1&&a%6!=5) return 0; int temp=sqrt(a); for(int i=5;i<=temp;i+=6) { if(a%i==0||a%(i+2)==0) return 0; } return 1; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x; scanf("%d",&x); if(su(x)) printf("Yes"),cout<<endl; //是質數 else printf("No"),cout<<endl; x=0;
} return 0; }
然而這個方法在一些時候是有弊病的。好比本題區間質數查詢時,有些數須要重複的判斷屢次。用這個方法就會T掉部分點。code
一位@Enderturtle大佬給出了另外一種方法。blog
因此說,對於不一樣的方法,還要注意看它們的優勢,適宜什麼狀況啊(嘆氣get
#include<cmath> #include<cstdio> #include<algorithm> using namespace std; int n,m; int tot[1000005]; bool book[1000005]; void prime(int f) { tot[1]=0; book[1]=true; for(int i=2;i<=f;i++) { if(book[i]==false) { tot[i]=tot[i-1]+1; for(int j=2*i;j<=f;j=j+i) { book[j]=true; } } else tot[i]=tot[i-1]; } } int main() { scanf("%d%d",&n,&m); prime(m); for(int i=1;i<=n;i++) { int l=0,r=0; scanf("%d%d",&l,&r); if(l<1||l>m||r<1||r>m) { printf("Crossing the line\n"); continue; } else { if(book[l]==false) { printf("%d\n",tot[r]-tot[l]+1); continue; } printf("%d\n",tot[r]-tot[l]); } } return 0; }
因此咱們換個角度從判斷素數,變成判斷合數;博客
合數顯然是能夠分解質因數的,既然如此,也就說明,質數的倍數(倍數>1)都是合數,因此就有了線性篩(不懂線性篩的同窗能夠看洛谷[【模板】線性篩素數](https://www.luogu.org/problemnew/show/3383 "【模板】線性篩素數"))it
本質上就是從2開始把它除自己的倍數所有刪去,以此類推(這時你可能要問那到這個數的時候怎麼判斷它是否是質數,事實上,若是天然數N在N-1的時候沒有把它標記掉就確定是質數(具體證實可百度))io
區間和能夠用前綴和處理;模板
f[r]-f[l],若是l是質數還要加1