nyoj password treasure box

password box

Time Limit: 2000 ms | Memory Limit: 65535 KB

Difficulty: 3

describe

Little M got a treasure box, but unfortunately, a set of magical passwords is required to open the treasure box, but under the treasure box

There are hints about the password: the password is a C-base number, and can only be composed of some of the given M numbers, the password does not exceed 500 digits, and the password is a positive integer with a given decimal integer N times,

If such a code exists, then you can open the treasure box and get the treasure, if not

Such a password...then you can only collect this treasure box.

enter

Enter a T, indicating that there are T groups of test data, (T≤500)
then enter N, C, M (N, C, M as described above) ( 0≤N≤5000, 1≤M≤16 , 2≤C ≤16 )
and then M numbers, indicating which numbers are contained in the password. (The input is guaranteed to be legal)
Use A to represent 10, B to represent 11, C to represent 12, D to represent 13, E to represent 14, F to represent 15

output

Output: If the password exists, enter the smallest one is the password, and there is no "So Sorry." (the password does not contain leading zeros)

sample input

3

22 10 3

7 0 1

 

2 10 1

1

 

25 16 3

A B C

Sample output

110

So Sorry.

CCB

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;

//Looking at the idea of ​​​​the great god, simulating the arithmetic operation of division, it can be seen that if there is the same remainder, a loop will occur, and the search status can be marked with the remainder
//mark mark, pre is the record path for finding the answer, ansAt: num
int mark[5005 obtained when res is i ],pre[5004],ansAt[5005],N,C,M,num[20];
char ans[5005];//Record the answer

char itoc(int i)
{
return i<10?(i+'0'):(i+'A'-10);
}

int ctoi(char i)
{
return i>='0'&&i<='9'?(i-'0'):(i-'A'+10);
}

bool bfs()
{
queue<int> q;
q.push(0);
while(!q.empty())
{
int temp=q.front();
q.pop();
for(int i=0; i<M;++i)
{
int res=(temp*C+num[i])%N;//The same remainder means repeated search
if(!mark[res]&&!(!temp&&!num[i] ))//Note that when temp and num are both 0, the remainder cannot be used to judge
{
mark[res]=true;
ansAt[res]=num[i];
pre[res]=temp;
if(res==0) //If the remainder is 0, it is divisible, find the answer
return true;
q.push(res);
}
}
}
return false;
}

bool check()
{
int temp=pre[0],i=0;
ans[i++]=itoc(ansAt[0]);

while(temp) //Construct result according to pre and ansAt
{
ans[i++]=itoc( ansAt[temp]);
temp=pre[temp];
}
ans[i]=0;
if(i<=500) //The correct result is less than 500 digits
return true;

return false;
}

int main()
{
int T;
string str;
cin>>T;
while(T--)
{
memset(mark,false,sizeof(mark));
memset(pre,0,sizeof(pre));

cin>> N>>C>>M;
for(int i=0;i<M;++i)
{
cin>>str; //The input may have hexadecimal characters, so the input is defined as string type, When converting to int type
num[i]=ctoi(str[0]); //char->int; When the input is less than 10, there is only one number per input, that is,
//that is, the first character str [0], when the letter is, the same way
}

sort(num,num+M); //sort to search from small to large

if(N==0)
{
if(num[0]==0) //0 Is to judge
cout<<'0'<<endl;
else
cout<<"So Sorry."<<endl;

continue;
}

if(bfs()&&check()) // found and the length is legal
{
for(int i=strlen(ans)-1;i>=0;--i)
cout<<ans[i];

cout<<endl;
}
else
cout<<"So Sorry."<<endl;
}
return 0;
}

Others don't understand too much. . Save it first

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325305814&siteId=291194637