• 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
  • 相关阅读:
    如何:为 Silverlight 客户端生成双工服务
    Microsoft Sync Framework 2.1 软件开发包 (SDK)
    Windows 下的安装phpMoAdmin
    asp.net安全检测工具 Padding Oracle 检测
    HTTP Basic Authentication for RESTFul Service
    Windows系统性能分析
    Windows Server AppFabric Management Pack for Operations Manager 2007
    Mongo Database 性能优化
    服务器未能识别 HTTP 标头 SOAPAction 的值
    TCP WAIT状态及其对繁忙的服务器的影响
  • 原文地址:https://www.cnblogs.com/OFSHK/p/11465622.html
Copyright © 2020-2023  润新知