线性筛素数
题目描述
给定一个范围 n,有 q 个询问,每次输出第 k 小的素数。
输入格式
第一行包含两个正整数 n,q分别表示查询的范围和查询的个数。
接下来 q行每行一个正整数 k,表示查询第 k小的素数。
输出格式
输出 q 行,每行一个正整数表示答案。
输入输出样例
输入
100 5
1
2
3
4
5
输出
2
3
5
7
11
#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=1000010;
int primes[MAXN],cnt;
bool num[MAXN];
void get_primes0(int n){//埃拉托斯特尼
for(int i=2;i<=n;i++){
if(!num[i]){//遇到质数i就把所有有i这个质因子的数筛掉
//不过不能保证每个数只被筛一次,如15=3*5,会被3和5各筛一次
primes[++cnt]=i;
for(int j=2;j*i<=n;j++) num[j*i]=true;
}
}
}
void get_primes(int n){//欧拉筛
for(int i=2;i<=n;i++){
//i如果是质数,一定没有除1和他本身的质因子,一定不会被筛掉
//i如果是合数,一定有一个最小质因子p,
//所以可以把i拆分成p 和i/p 两个整数
//其中i/p这个数最小质因子一定大于等于p,
//所以在处理i/p这个数的时候一定把i筛了
//所以任意合数i都一定在遍历i之前就被筛掉了。
//所以任意合数都被筛掉了
if(!num[i]) primes[++cnt]=i;
for(int j=1;primes[j]*i<=n;j++){
num[primes[j]*i]=true;
if(i%primes[j]==0) break;
//保证i*ps[j]这个数要被筛掉的话,一定是被它的最小质因子i筛掉。
//所以i*ps[j]只会被筛一次
//所以任意合数只会被筛一次
}
}
int main(){
int n;
scanf("%d",&n);
get_primes(n);
printf("%d",cnt);
return 0;
}