题目描述
如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内)
输入输出格式
输入格式:
第一行包含两个正整数N、M,分别表示查询的范围和查询的个数。
接下来M行每行包含一个不小于1且不大于N的整数,即询问该数是否为质数。
输出格式:
输出包含M行,每行为Yes或No,即依次为每一个询问的结果。
输入输出样例
说明
时空限制:500ms 128M
数据规模:
对于30%的数据:N<=10000,M<=10000
对于100%的数据:N<=10000000,M<=100000
样例说明:
N=100,说明接下来的询问数均不大于100且不小于1。
所以2、3、97为质数,4、91非质数。
故依次输出Yes、Yes、No、No、Yes。
解题思路:
此题运用埃拉托斯特尼筛法(埃氏筛),一种由古希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。
埃氏筛:
1 #include<iostream> 2 using namespace std; 3 int n,m; 4 bool a[10000001]; 5 void shai(){ 6 for(int i = 2;i <= n;i++) 7 a[i] = true; 8 for(int i = 2;i <= n;i++) 9 if(a[i]) 10 for(int x = i+i;x <= n;x += i) 11 a[x] = false; 12 13 } 14 int main(){ 15 cin >> n >> m; 16 shai(); 17 for(int i = 1;i <= m;i++) { 18 int l; 19 cin >> l; 20 (a[l]) ? cout << "Yes" <<endl : cout << "No" <<endl; 21 } 22 return 0; 23 }
欧拉筛:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 5 using namespace std; 6 7 int n,m,prim[670000],tot; 8 bool vis[10000001]; 9 10 inline void oula() { 11 memset(vis,1,sizeof(vis)); 12 vis[1] = vis[0] = 0; 13 for(int i = 2;i <= n; i++) { 14 if(vis[i]) prim[++tot] = i; 15 for(int j = 1;j <= tot; j++) { 16 if(prim[j] * i > n) break; 17 vis[prim[j]*i] = 0; 18 if(i % prim[j] == 0) break; 19 } 20 } 21 } 22 23 inline void work() { 24 for(int i = 1;i <= m; i++) { 25 int x; 26 scanf("%d",&x); 27 if(vis[x]) printf("Yes "); 28 else printf("No "); 29 } 30 } 31 32 int main() { 33 scanf("%d%d",&n,&m); 34 oula(); 35 work(); 36 return 0; 37 }