牛客小白月赛56:D、阿宁的质数

1,236 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情

题目描述

阿宁有一个长度为 n 的正整数数组 a,她有很多次询问,每次询问:在数组 a 的前 x 个数中,未出现的最小质数是多少?

输入描述:

第一行输入两个正整数 n,q 表示数组的长度和询问的次数。
第二行输入 n 个正整数 ai​,表示数组的每一个元素。
接下来 q 行,每行一个正整数 x,代表一次询问。

1≤n,q2×10^5
1≤ai≤10^9
1≤x≤n

输出描述:

输出 q 行,表示每次询问的答案。

示例1

输入
5 5
8 2 3 6 5
1
2
3
4
5

输出
2
3
5
5
7

说明

8 不是质数,未出现的最小质数是 2。
在 8,2 中,质数有 2,未出现的最小质数是 3。
在 8,2,3 中,质数有 2,3,未出现的最小质数是 5。
在 8,2,3,6 中,质数有 2,3,未出现的最小质数是 5。
在 8,2,3,6,5 中,质数有 2,3,5,未出现的最小质数是 7。

问题解析

既然题目要求输出前x个数内没出现的质数,那么我们可以先从2开始算出一定量的质数,然后再从数组的前x个数里开始比较,看那些质数没有出现过。

算出多少质数合适呢?数组的最大长度是2e5,所以极端情况下我们至少要处理出2e5+1个质数,即数组的数全都是质数。而大概2到3e6之间就有这么多的质数。那么我们可以先用质数筛筛出2到3e6之间所有的质数。然后在处理每次询问。

但如果对于每次询问,我们都重新计算一遍结果,显然是不行的。所以我们应该对于x=(1,2,……,n)先预处理所有的结果,把结果都存入数组f中,那么对于每个询问,答案就是:f[x]。

(具体看代码)

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>

//#pragma GCC optimize(3)

#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e7 + 50, MOD = 1e11 + 3;

//p数组存放的是质数,cnt是质数个数
int p[N], cnt;
//st[i]表示第i个数是否是质数
bool st[N];

//质数筛
void get_primes()
{
    int n =3e6;
    for (int i = 2; i <= n; i++)
    {
        if (!st[i])p[cnt++] = i;
        for (int j = 0; p[j] <= n / i; j++)
        {
            st[i * p[j]] = true;
            if (i % p[j] == 0)break;
        }
    }
}

void solve()
{
    get_primes();
    int n, q;
    cin >> n >> q;
    vector<int>v(n+1), f(n+1);
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i];
    }
    //p数组的下标,p[l]就是目前没出现过的最小质数
    int l = 0;
    //记录数出现的次数
    unordered_map<int, int>mymap;
    for (int i = 1; i <= n; i++)
    {
        
        mymap[v[i]] = 1;
        //如果这个质数出现过了,下标++
        while (mymap[p[l]] == 1)
            l++;
        //记录答案
        f[i] = p[l];
    }
    while (q--)
    {
        int x;
        cin >> x;
        cout << f[x] << endl;
    }
}


signed main()
{

    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}