洛谷P3383 【模板】线性筛素数(即欧拉筛)

题目背景

本题已更新,从判断素数改为了查询第 kk 小的素数
提示:如果你使用 cin 来读入,建议使用 std::ios::sync_with_stdio(0) 来加速。

题目描述

如题,给定一个范围 nn,有 qq 个询问,每次输出第 kk 小的素数。

输入格式

第一行包含两个正整数 n,qn,q,分别表示查询的范围和查询的个数。

接下来 qq 行每行一个正整数 kk,表示查询第 kk 小的素数。

输出格式

输出 qq 行,每行一个正整数表示答案。

输入输出样例

输入 #1复制

100 5
1
2
3
4
5

输出 #1复制

2
3
5
7
11

说明/提示

【数据范围】
对于 100\%100% 的数据,n = 10^8n=108,1 \le q \le 10^61≤q≤106,保证查询的素数不大于 nn。

Data by NaCly_Fish.

  

这道题用埃式筛解题也不是不可以,不过应该会超时

所以这道题考察我们的应该是线性筛(即欧拉筛,下同)

而欧拉筛法的思想非常简单,就是我们要求每一个数都被且仅被其最小的质因数筛掉(这也是欧拉筛对于埃氏筛法的一个优化),这使得它的时间复杂度仅有O(n)

而有些同学可能要问了:埃式筛又是什么呢?

埃式筛的大体思想:要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。(详见百度百科)

那么代码如下:

#include <bits/stdc++.h>
using namespace std;
bool a[100000001];
/*
a数组存储筛法表(0代表不是质数,1代表是质数),并且这里要注意,因为题目输入的数据比较大,
a数组开long long或int会爆空间!
*/ 
int p[700000],s = 0;//p数组储存质数表,s储存目前p数组中有几个质数(其实就是质数表目前要赋值的下标) 
void pri(int n)//在1-n的范围内处理质数 
{
  for(int i = 2; i <= n; i++)
  {
    if(a[i] == 1)//如果a[i]是质数 
    {
      s++;//则质数表长度+1 
      p[s] = i;//再把该数字填入表中 
    }
    for(int j = 1; j <= s && i * p[j] <= n; j++)//j遍历质数表,并且i * p[j]还不能超过范围(也就是n) 
    {
      a[i * p[j]] = 0;//因为i * p[j]一定是合数 
      if(i % p[j] == 0) break;
      /*
      如果这是第一次筛掉它,就直接break
      (因为欧拉筛只被它的最小的质因子筛掉,这也是它对埃氏筛的剪枝操作)
      */ 
    }
  }
}
int main()
{
  int n,q;//n是质数范围,q是有几组数据 
  cin>>n>>q;
  memset(p,1,sizeof(a));//初始化成1(因为1代表是质数,后期在pri函数中再刷掉合数) 
  a[1] = 0;//因为1不是质数 
  pri(n);//欧拉筛 
  for(int i = 0; i < q; i++)//预处理完后再输入 
  {
    int k;
    cin>>k; 
    cout<<p[k]<<endl;//直接调用质数表中的第k个 
  }
  return 0;
} 

如果这篇文章对您有帮助的话,请记得点赞收藏加关注吖(●'◡'●)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值