zoukankan      html  css  js  c++  java
  • HDU1226超级密码队列+广搜+大数取模

    Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 
    密码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧. 

    注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在. 

    Input

    输入数据的第一行是一个整数T(1<=T<=300),表示测试数据的数量.每组测试数据的第一行是两个整数N(0<=N<=5000)和C(2<=C<=16),其中N表示的是题目描述中的给定十进制整数,C是密码的进制数.测试数据的第二行是一个整数M(1<=M<=16),它表示构成密码的数字的数量,然后是M个数字用来表示构成密码的数字.两个测试数据之间会有一个空行隔开. 

    注意:在给出的M个数字中,如果存在超过10的数,我们约定用A来表示10,B来表示11,C来表示12,D来表示13,E来表示14,F来表示15.我保证输入数据都是合法的. 

    Output

    对于每组测试数据,如果存在要求的密码,则输出该密码,如果密码不存在,则输出"give me the bomb please". 

    注意:构成密码的数字不一定全部都要用上;密码有可能非常长,不要试图用一个整型变量来保存密码;我保证密码最高位不为0(除非密码本身就是0). 

    Sample Input

    3
    22 10
    3
    7 0 1

    2 10
    1
    1

    25 16
    3
    A B C


    Sample Output

    110
    give me the bomb please
    CCB

    Huge input, scanf is recommended.

    思路:

    先将题目给的m个字符进行标记,先进行第一轮循环,看看是否有个位数直接是n的倍数(0除外,因为题目规定最高位不能为0)再开始进队列,进行广搜。

    需要注意的细节:
    1、输入用%s输入单个字符,因为存在空格,%s不接收空格,%c会接收空格

    2、大数取模公式:(a+b)%m=(a%m+b%m)%m

    例如:175%6 =(100+70+5)%6 =100%6+70%6+5%6 =(100%6+70%6+5%6)%6;

    int sum=0;
    for(int i=0;i<na.len;i++)
        sum=(sum*10+a[i]-'0')%n;
    return sum;

    a%m=a%m%m,多取几次模对低位是没有影响的。

     该题:

    int sum=0;
    for(int i=0; i<p.l; i++)//p.l密码的长度
    {
        sum=(sum*c+p.str[i])%n;//c是几进制
    }
     return sum;

    3、队列基本操作:

    back()返回最后一个元素

    empty()如果队列空则返回真

    front()返回第一个元素

    pop()删除第一个元素

    push()在末尾加入一个元素

    size()返回队列中元素的个数

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    char mm[1];
    int book[20],out[5050],n,c,m;
    int flag;
    struct node
    {
        int str[555];//存密码
        int l;//密码长度
    } p,q;
    void shuchu(node p)
    {
        for(int i=0; i<p.l; i++)
        {
            if(p.str[i]<=9)
                printf("%d",p.str[i]);
            else
                printf("%c",p.str[i]+55);
        }
        flag=1;
        printf("\n");
        return ;
    }
     
    int quyu(node p)
    {
    //        int sum=p.str[p.l-1];
    //      for(int i=p.l-2; i>=0; i--)
    //      {
    //          sum=(sum+(p.str[i]*c)%n)%n;
    //          c=c*c;
    //      }
    //      return sum;
        int sum=0;
        for(int i=0; i<p.l; i++)
        {
            sum=(sum*c+p.str[i])%n;
        }
        return sum;
    }
    void bfs()
    {
        memset(out,0,sizeof(out));//标记余数
        queue<node>Q;
        p.l=0;
        int yushu;
        for(int i=1; i<16; i++) //先走第一遍,让系统给的mm里面的每一个元素作为队头,因为可能第一遍给的数据就是最小倍数
            //因为0不能作为开头,所以走第一遍的时候遍历从1开始;
        {
            if(book[i]==1)//如果题目给了该数字
            {
                p.str[0]=i;//后面的不断覆盖前面的,因为刚开始第一步只有一步
                p.l=1;//进来一个元素,长度改变为1,因为不断覆盖且只进行第一步,所以长度始终为1,不需要++
                yushu=quyu(p);
                if(yushu==0)//说明找到了
                {
                    shuchu(p);
                    flag=1;
                    break;
                }
                else
                {
                    //第一遍遍历没有找到,且如果这个余数之前没有出现过的话,把该余数标记一下
                    if(out[yushu]==0)
                    {
                        out[yushu]=1;
                        Q.push(p);//在队尾加入一个元素
                    }
                }
                //printf("%d--",flag);
            }
        }
        while(!Q.empty())
        {
     
            if(flag)
                break;
            //node p;
            p=Q.front();//返回到第一个元素
            Q.pop();//删除第一个元素
            for(int i=0; i<16; i++) //接着一条条队列开始进行搜索
            {
                if(book[i]==1)//如果是题目给定的那几个数字就往下进行
                {
                    //printf("%d-- ",i);
                    p.str[p.l]=i;//之前第一遍遍历的时候存的位置是l=0的位置,后来l变成1了,所以这里不需要++,直接占用l=1的位置
                    //之后再++,给下一位存入的数字留一个位置
                    p.l++;
                    yushu=quyu(p);
                    if(yushu==0)//找到了
                    {
                        shuchu(p);
                        flag=1;
                        break;
                    }
                    else
                    {
                        //if(out[yushu]==0&&(a.l-1<=497))//注意一下长度需要控制,并且是从l=0开始存的
                        if(out[yushu]==0&&(p.l<=498))
                        {
                            out[yushu]=1;
                            Q.push(p);
                        }
                        p.l--;//这步很重要,非常重要
                    }
                }
            }
        }
        return ;
    }
    int main()
    {
        int t;
        while(~scanf("%d",&t)&&t)
        {
            while(t--)
            {
                flag=0;
                memset(book,0,sizeof(book));
                scanf("%d %d",&n,&c);
                scanf("%d",&m);
    //            for(int i=0; i<m; i++)
    //            {
    //                scanf("%c",&mm[i]);
    //                if(mm[i]>='0'&&mm[i]<='9')
    //                    book[mm[0]-48]=1;
    //                if(mm[i]>='A'&&mm[i]<='F')
    //                    //book[mm[i]-65+10]=1;
    //                    book[mm[i]-55]=1;
    //            }//注意一下这里的输入,不能用%c,因为它接收空格,一开始记错了
                for(int i=0; i<m; i++)
                {
                    scanf("%s",mm);
                    if(mm[0]>='0'&&mm[0]<='9')
                        book[mm[0]-48]=1;
                    if(mm[0]>='A'&&mm[0]<='F')
                        //book[mm[i]-65+10]=1;
                        book[mm[0]-55]=1;
                }
                if(n==0)
                {
                    if(book[0]==0)//说明给的几个数中没有0,该密码无法构成,故不存在
                        printf("give me the bomb please\n");
                    if(book[0]==1)//说明给的几个数中有0,该密码最小倍数为0
                        printf("0\n");
                }
                else
                {
                    bfs();
                    if(flag==0)//return为0,说明没有找到密码,不然就在上面输出了(return为1)
                        printf("give me the bomb please\n");
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Solution -「ARC 126F」Affine Sort
    Solution -「ABC 219H」Candles
    Solution -「LOCAL」二进制的世界
    Solution Set -「ABC 217」
    Java 封装
    Java 对象和类
    Java 继承
    牛客网MySQL在线编程
    Linux uniq命令
    Linux 单引号、双引号、反引号
  • 原文地址:https://www.cnblogs.com/OFSHK/p/11465622.html
Copyright © 2011-2022 走看看