【[NOIP2021] 报数】题解

· · 题解

前言

于是我就愉快的 AC 了 。

希望审核能给我过了这篇题解 。

题目

题目传送门

正文

题目大意是数位中含有 7 的数不能报出 , 并且它的倍数也不能报出 。 ( 7 也是数位中含有 7 的数 )

所以我们要枚举出不能报出的数:

void init()
{
    for(int i=1;i<=maxn;i++)
    {
        if(retire[i]) continue;
        if(i%10==7||i/10%10==7||i/100%10==7||i/1000%10==7||i/10000%10==7||i/100000%10==7||i/1000000%10==7||i/10000000%10==7)
        {
            retire[i]=1;
            for(int j=i+i;j<=maxn;j+=i)
            {
                retire[j]=1;
            }
        }
    }
}

预处理没了,接下来就好做了。

判断这个数是不是能报出的,如果不能,输出 -1 。 如果能 , 就往后找可输出的数,然后输出。

但是 , 如果给你一组数据 :

100000
699999
699999
699999
699999
699999
…
699999
//有 100000 个 6999999

那么肯定超时,所以我们要用到记忆化数组 。

long long find_sum[10010005];

它可以将当前数要输出的数记忆下来 , 等到又输入同样的数时 , 直接输出 。

AC code:(有大量注释帮助理解)

#include<cstdio>
using namespace std;
inline long long read()//快读 
{
    long long s=0,f=1;
    char a = getchar();
    while(a<'0'||a>'9')
    {
        if(a=='-') 
        {
            f=-1; 
            a=getchar();
        }
    }
    while(a <= '9' && a >= '0') s = s * 10 + a - '0', a = getchar();
    return s * f;
}
const long long maxn=1e7+1e4;//有些情况需报出比题目数据大的数,这些数也要处理 
long long n,retire[maxn+5],AFO;
long long find_sum[maxn+5];//记忆化 
void init()//枚举不可报出的数 
{
    for(int i=1;i<=maxn;i++)
    {
        if(retire[i]) continue;//已经处理过了,跳过 
        if(i%10==7||i/10%10==7||i/100%10==7||i/1000%10==7||i/10000%10==7||i/100000%10==7||i/1000000%10==7||i/10000000%10==7)//判断数中有没有7 
        {
            retire[i]=1;//处理当前数 
            for(int j=i+i;j<=maxn;j+=i)
            {
                retire[j]=1;//将它的倍数也处理了 
            }
        }
    }
}
int main()
{
    init(); 
    n=read();
    while(n--)
    {
        AFO=read(); 
        if(retire[AFO]) printf("-1\n");//如果它不可报出 
        else
        {
            if(find_sum[AFO])//如果它报出过,直接输出应报出的数 
            {
                printf("%d\n",find_sum[AFO]);
            }
            else
            {
                int JC=AFO+1;//不能报出当前数 
                while(retire[JC])//查找下一个可报出的数 
                {
                    JC++;
                }
                find_sum[AFO]=JC;//记忆化 
                printf("%d\n",find_sum[AFO]);
            }
        }
    }
}

最后希望这篇题解能帮到屏幕前的你,但是不要抄袭哦!