HDOJ 1226 超级密码

时间:2024-03-24 22:05:38

超级密码

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1492    Accepted Submission(s): 445

Problem Description
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
Hint

Hint

Huge input, scanf is recommended.

Author
Ignatius.L
Source
Recommend
Ignatius.L

r= k (mod c)則 (k*p+a)(mod c)=(r*p+a)(mod c)

若是某个数&#20540;序列的余数为r.....若是某个余数已经被机关过...那么后面获得的必然是与本来机关过的余数序列雷同的序列 而由BFS的性质.最短的必然是最先被机关出来的..所以.....先到先得!(每一位应用什么数字都是不变的哦.....就是在同一个数&#20540;凑集内...).  若是看不懂 看下面的

例如 若是 k1%c==k1k2%c   则 k1k3%c==k1k2k3%c

再特别一点的 比如 3%4==3    27%4==3  则 31%4==271%4 ,32%4==272%4  ,33%4==273%4...............

我们请求得的数是n的整数倍 即余数为0  则取余数为0的数中的最小的那个即可

若是请求余数为k的数  只请求出最短的序列 因为n<5000余数最多有5000个  用BFS搜刮 余数第一次呈现的地位就是最短的序列 从中我们找出余数为0对应的最短的序列即可

结论:只要某种余数曾经呈现过.那么这种余数就不须要再呈现.....  直到找到余数为0   或者长度大于500就退出

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <queue> using namespace std; const int maxn=;
const int maxm=; bool mod[maxm];
char arr[];
int digit[]; struct Node
{
char str[maxn];
int len;
}ans; int N,C,M; int judge(Node X)
{
int sum=;
int len=X.len;
int OK=;
for(int i=;i<len;i++)
{
if(X.str[i]!='')
{
OK=;
break;
}
}
if(!OK) return ;
for(int i=;i<len;i++)
{
if(X.str[i]>=''&&X.str[i]<='')
{
sum=(sum*C+(X.str[i]-''))%N;
}
else if(X.str[i]>='A'&&X.str[i]<='F')
{
sum=(sum*C+(X.str[i]-'A'+))%N;
}
}
sum=sum%N;
return sum;
} queue<Node> q; int bfs()
{ Node x,y; while(!q.empty())
{ y=q.front();
q.pop();
int MOD1; // if(y.len==3&&y.str[0]=='1'&&y.str[1]=='1'&&y.str[0]=='0') cout<<"miaomiaoishere\n"; if((MOD1=judge(y))==)
{
ans=y;
int len=ans.len;
for(int i=;i<len;i++)
printf("%c",ans.str[i]);
putchar();
return ;
}
int zero=;
// if(y.len==1) zero=1;
for(int i=zero;i<;i++)
{
if(digit[i])
{
x=y;
if(i>=&&i<)
x.str[x.len]=i+'';
else if(i>=&&i<=)
x.str[x.len]=i-+'A';
x.len=x.len+;
int MOD2=judge(x);
if(x.len+<=&&mod[MOD2]==false&&MOD2!=)
{
mod[MOD2]=true;
q.push(x);
}
}
}
}
return ;
} int main()
{int T;
scanf("%d",&T);
while(T--)
{
memset(mod,false,sizeof(mod));
memset(digit,,sizeof(digit));
while(!q.empty()) q.pop(); scanf("%d%d%d",&N,&C,&M);
getchar();
for(int i=;i<M;i++)
{
scanf("%c",&arr[i]);
getchar();
if(arr[i]<=''&&arr[i]>='')
digit[arr[i]-'']=;
else if(arr[i]<='F'&&arr[i]>='A')
digit[arr[i]-'A'+]=;
}
Node xt;
for(int i=;i<=;i++)
{
if(digit[i])
{
if(i>=&&i<)
xt.str[]=i+'';
else if(i>=&&i<=)
xt.str[]=i-+'A';
xt.len=;
q.push(xt);
// int MOD=judge(xt);
// mod[MOD]=true;
}
}
// cout<<q.size()<<"----------\n";
// getchar(); if(N==)
{
if(digit[]) puts("");
else puts("give me the bomb please");
}
else
{
if(bfs())
{
}
else
puts("give me the bomb please");
} } return ;
}