HDU 1226 超级密码[广搜]
题意:
Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:
密码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧.
注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在.
密码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧.
注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在.
分析:大数取模+广搜。注意0的情况,这题只算0是0的倍数。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int n, c, m; int a[17]; int pre[10000]; int q[1000000]; int num[1000000]; int v[5005]; bool flag; int res; void bfs() { int i, j; int front=0, rear=0; for (i=0; i<m; i++) { if (v[a[i]%n] || a[i]==0) continue; num[rear] = a[i]; q[rear++] = a[i]%n; v[a[i]%n] = 1; } int tt, in; while (front < rear) { tt = q[front]; if (tt==0) { flag = true; res = front; break; } for (i=0; i<m; i++) { in = (tt*c+a[i])%n; if (!v[in]) { v[in] = v[tt]+1; if (v[in]<=500) { q[rear] = in; num[rear] = a[i]; pre[rear]=front; rear++; } } } front++; } } void print(int i) { if (i==-1) return; print(pre[i]); printf("%c",num[i]<10?num[i]+'0':num[i]-10+'A'); } int main() { int t; int i, j, k; scanf("%d",&t); while (t--) { scanf("%d %d",&n,&c); scanf("%d",&m); for (i=0; i<m; i++) { char s[2]; scanf("%s",s); if (s[0]>='A' && s[0]<='F') a[i] = s[0]-'A'+10; else a[i] = s[0]-'0'; } sort(a,a+m); memset(pre,-1,sizeof(pre)); memset(v,0,sizeof(v)); flag = false; if(n==0){ if(a[0]==0) printf("0\n"); else printf("give me the bomb please\n"); continue; } bfs(); if (flag){ print(res); printf("\n"); } else printf("give me the bomb please\n"); } return 0; }