素数筛

题目描述

如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内)

输入输出格式

输入格式:
第一行包含两个正整数N、M,分别表示查询的范围和查询的个数。

接下来M行每行包含一个不小于1且不大于N的整数,即询问该数是否为质数。

输出格式:
输出包含M行,每行为Yes或No,即依次为每一个询问的结果。

输入输出样例

输入样例#1: 复制
100 5
2
3
4
91
97
输出样例#1: 复制
Yes
Yes
No
No
Yes
说明

时空限制: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。

埃氏筛法

先将2~n的数写下,将2的倍数都去掉,然后是3的倍数...以此类推。时间复杂度大于O(n)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=10000005;
int n,m;
bool b[maxn];
int main() {
    scanf("%d%d",&n,&m);
    b[1]=1;     //1不为素数。 
    for(register int i=2; i<=n; i++) {
        for(int j=i; j<=n/i; j++) {
            b[i*j]=1;
        }
    }
    for(register int i=1;i<=m;i++){
        int x;
        scanf("%d",&x);
        if(b[x])    printf("No
");
        else    printf("Yes
");
    }
    return 0;
}

②线性筛优化

埃氏筛会造成重复筛数,比如18,2*9与3*6都筛过一次,影响效率。优化则是先将2的倍数筛去,再将素数记录到一个数组中,奇数则将奇数与数组中所有数的乘积筛去。
#include<bits/stdc++.h>
using namespace std;
const int maxn=100000005;
int n,m,cnt=1,a[maxn];
bool b[maxn];
int main(){
    scanf("%d%d",&n,&m);
    b[1]=1;            //1不为素数。
    a[1]=2;            //第一个素数为2。
    b[4]=1;            //4不为素数
    for(register int i=3;i<=n/2+1;i++){  //循环只需要到n/2+1即可。
        if(i%2==0)    
            b[i*2]=1;
        else{
            a[++cnt]=i;      //记录素数
            for(register int j=1;j<=cnt;j++){
                if(i*a[j]>n)    break;
                b[i*a[j]]=1;      //筛
            }
        }
    }
    for(int i=1;i<=m;i++){
        int x;
        scanf("%d",&x);
        if(b[x])    printf("No
");
        else    printf("Yes
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9677202.html