//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

NOIP 2021 报数

最暴力的方法就是先判断一个数的因子里是不是有数位上是 \(7\) 的,然后枚举判断后面的直到合法。

但是肯定不优,每次的判断至少是根号级别的,而且还要枚举找下一个。

观察值域只有 \(1e7\),不难想到可以用一个线性的预处理来做到近似 \(O(1)\) 的查询。

对于每一个数,暴力判断是不是数位上有 \(7\),然后再枚举倍数直到超出值域,效率和素数的埃氏筛差不多。

考虑一个数 \(p\) 若之前已经被筛出去过了,那么他的倍数,肯定在那次循环也被筛出去了,可以直接退出。

这样基本能保证每一个数只能筛一次,所以接近 \(O(S)\)\(S\) 为值域。

因为判断一个数是不是数位有 \(7\)\(log_{10}\) 的复杂度,所以当场数忽略掉。

对于查询下一个合法的值,这里将合法的值用一个数组存起来,用 upper_bound() 查找直接输出即可。


/*
 * @Author: Aisaka_Taiga
 * @Date: 2023-10-27 14:22:58
 * @LastEditTime: 2023-10-27 14:55:15
 * @LastEditors: Aisaka_Taiga
 * @FilePath: \Desktop\P7960.cpp
 * The heart is higher than the sky, and life is thinner than paper.
 */
#include <bits/stdc++.h>

#define int long long
#define N 10001000
#define M 10000100
#define endl '\n'

using namespace std;

inline int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
    while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}

int p[N], cnt, vis[N];

inline int pd(int x)
{
    int ff = 0;
    while(x)
    {
        if(x % 10 == 7) ff = 1;
        x /= 10;
    }
    return ff;
}

inline void init()
{
    for(int i = 1; i <= M; i ++)
    {
        if(!pd(i) && !vis[i]){p[++ cnt] = i; continue;}
        if(vis[i]) continue;
        vis[i] = 1;
        for(int j = 1; j * i <= M; j ++)
        {
            // cout << " J :  " << j << endl;
            vis[i * j] = 1;
            // if(vis[i * j]) break;
            // if(i % pp[j] == 0) break;
        }
    }
    return ;
}

inline void work()
{
    int n = read();
    if(vis[n]) cout << "-1" << endl;
    else
    {
        int k = upper_bound(p + 1, p + cnt + 1, n) - p - 1;
        cout << p[k + 1] << endl;
    }
    return ;
}

signed main()
{
    init();
    // cout << "OK" << endl;
    int T = read();
    while(T --) work();
    return 0;
}
posted @ 2023-10-27 15:05  北烛青澜  阅读(18)  评论(0编辑  收藏  举报