Description
Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:
密码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧.
注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在.
密码是一个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.我保证输入数据都是合法的.
注意:在给出的M个数字中,如果存在超过10的数,我们约定用A来表示10,B来表示11,C来表示12,D来表示13,E来表示14,F来表示15.我保证输入数据都是合法的.
Output
对于每组测试数据,如果存在要求的密码,则输出该密码,如果密码不存在,则输出"give me the bomb please".
注意:构成密码的数字不一定全部都要用上;密码有可能非常长,不要试图用一个整型变量来保存密码;我保证密码最高位不为0(除非密码本身就是0).
注意:构成密码的数字不一定全部都要用上;密码有可能非常长,不要试图用一个整型变量来保存密码;我保证密码最高位不为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.
这个题虽然A过了,但是基本上是抄的网上大牛们的代码,自己完全写不出来啊,还有其中那个余数的问题,看网上那个答案,看不明白是什么意思啊,哪位大牛能给详细介绍一下,谢谢
为什么前面出现的余数,在后面的数列中,如果该数列的余数在前面出现过的余数中,那么该数列就不能作为一个扩展数列而不能进入队列中?????不明白啊
大牛们的AC代码:
#include<iostream> #include<queue> #include<stack> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> int t,n,c,m,l; char num[16]; char book[5001]; using namespace std; struct Node{ int s[501]; int len; }; int mod(Node a) { int temp=0; for(int i=0;i<a.len;i++) { temp=(temp*c+a.s[i])%n; } return temp; } void Print(Node a) { for(int i=0;i<a.len;i++) { if(a.s[i]<=9) printf("%d",a.s[i]); else { printf("%c",a.s[i]+'A'-10);//因为A~F对应的十进制数是由 cc-'A'+10得来的,再倒着回去 } } printf("\n"); } int bfs() { Node a; queue<Node> Q; a.len=0; int i,r; for(int i=1;i<16;i++)//这里进行的是一位数的搜索,因为首位数字不能为0,所以i从1开始 { if(num[i])//必须是出现过的数字,才能进行扩展 { a.s[0]=i; a.len=1; r=mod(a);//进行判断余数的情况 if(r==0) { Print(a); return 1; } else { if(book[r]==0)//前面出现过的余数,在后面要探索的数列中,如果该数列的余数在前 { //面出现过,那么该数列不能进入队列 book[r]=1; Q.push(a); } } } } while(!Q.empty()) { a=Q.front(); Q.pop(); for(int i=0;i<16;i++) { if(num[i]) { a.s[a.len]=i;//增加一位 a.len++; r=mod(a); if(r==0) { Print(a); return 1; } else { if(book[r]==0 && a.len<499)//最大位数是500,数组的话最大是499,但是 { //每次入队列的数列都是为了下次扩展的时候,把 book[r]=1; //数列扩大一位,如果是499的话,再扩展就超出 Q.push(a); //500的范围了 } } a.len--;//这里减减是为了,在该位数时进行搜索时,确保搜的数位数是一样的 } } } return 0; } int main() { char s[2]; scanf("%d",&t); while(t--) { memset(book,0,sizeof(book)); memset(num,0,sizeof(num)); scanf("%d%d%d",&n,&c,&m); for(int i=0;i<m;i++) { scanf("%s",s); if(s[0]-'0'>=0 && s[0]-'0'<=9) num[s[0]-'0']=1; else num[s[0]-'A'+10]=1; } if(n) { int flag; flag=bfs(); if(flag==0) printf("give me the bomb please\n"); } else { if(num[n])//处理密码是0的问题 ,如果改密码是的倍数是0 ,并且在所给的数字中出现了0, printf("0\n");// 那么密码就是0了,否则密码不存在 else printf("give me the bomb please\n"); } } return 0; }