Yet Another Multiple Problem (hdu 4474)

There are tons of problems about integer multiples. Despite the fact that the topic is not original, the content is highly challenging. That’s why we call it “Yet Another Multiple Problem”.
In this problem, you’re asked to solve the following question: Given a positive integer n and m decimal digits, what is the minimal positive multiple of n whose decimal notation does not contain any of the given digits?
 


Input
There are several test cases.
For each test case, there are two lines. The first line contains two integers n and m (1 ≤ n ≤ 104). The second line contains m decimal digits separated by spaces.
Input is terminated by EOF.
 


Output
For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) while Y is the minimal multiple satisfying the above-mentioned conditions or “-1” (without quotation marks) in case there does not exist such a multiple.
 


Sample Input
2345 3
7 8 9
100 1
0
 


Sample Output
Case 1: 2345
Case 2: -1
 


Source
2012 Asia Chengdu Regional Contest
 


Recommend

liuyiding


题目分析:接触到这道题目时,我和队友们想的暴力一倍倍的加上去,然后加个卡时,结果一遍又一遍的超时、wrong answer,现在想想,觉得当时好傻,非常不理智。
这题的主要思想是bfs,将可以使用的数字按字典序最小的顺序bfs,直到搜出能整除n的数。裸bfs的话无疑会超时的,我们发现,n是小于10000的,
也就是说对n取余后的数也是小于10000的,这方面是否可以做点文章呢,其实,如果两个数对n取余的余数是一样的话,那个大一点的数完全没有考虑的必要了,则可以用一个bool型数组记录所得的余数,这样扩展的节点大概是10000左右,效率大幅度提高,174ms AC,题目给的20000ms太浪费了,呵呵。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
struct
{
    int r; //当前节点的余数
    int f; //当前节点的父指针
    char c;//当前节点余数的最后一位
} q[10005],tmp;
void print(int k)
{
    if (q[k].f!=-1)
    {
        print(q[k].f);
    }
    printf ("%c",q[k].c);
}
int main()
{
    int n,m,x,l,r,res,i;
    bool vis[10],p[10005];
    int CASE=1;
    while (~scanf("%d%d",&n,&m))
    {
        memset(vis,true,sizeof(vis));
        while (m--)
        {
            scanf("%d",&x);
            vis[x]=false;
        }
        l=1; r=0;
        res=0;
        memset(p,false,sizeof(p));
        for (i=1;i<10;i++)
        if (vis[i]&& !p[i%n])
        {
            r++;
            p[i%n]=true;
            q[r].c=i+'0';
            q[r].r=i%n;
            q[r].f=-1;
            if (i%n==0)
            {
                res=r;
                break;
            }
        }
        while (l<=r&& !res)
        {
            for (i=0;i<10;i++)
            if (vis[i])
            {
                tmp.c=i+'0';
                tmp.r=(q[l].r*10+i)%n;
                tmp.f=l;
                if (!p[tmp.r])
                {
                    r++;
                    q[r]=tmp;
                    p[tmp.r]=true;
                    if (tmp.r==0)
                    {
                        res=r;
                        break;
                    }
                }
            }
            l++;
        }
        if (! res) printf("Case %d: -1\n",CASE++);
        else
        {
            printf("Case %d: ",CASE++);
            print(res);
            printf("\n");
        }
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值