这道题就是给你M个C进制的数, 然后让你求最小的数, 这个数是N的整数倍。。搜索即可:剪枝条件:假设有两个数模N都为0那么我们就可以舍弃较大的那个数。为什么可以这样,我们可以假设这两个数是a, b a = b (mod N) => a*C + d = b*C + d (mod N), 然后注意取模的时候要用大数取摸的方式。。坑点:N可能为0, 对于N==0的时候,我们应该特殊判断, 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; int N, C, M; //c进制的密码 char num[20]; struct State { char st[505]; int len; }temp, res; int vis[5000 + 10]; int mod(State &st) { int tmp = 0; for(int i=0; i<st.len; i++) { int num; if(st.st[i]>=‘0‘ && st.st[i]<=‘9‘) num = st.st[i] - ‘0‘; else if(st.st[i]>=‘A‘ && st.st[i]<=‘F‘) num = st.st[i]-‘A‘+10; tmp = (tmp*C + num)%N; } return tmp; } void print(State &u) { for(int i=0; i<u.len; i++) { printf("%c", u.st[i]); } printf("\n"); } int bfs() { memset(vis, 0, sizeof(vis)); queue<State> que; for(int i=0; i<M; i++) { temp.len = 1; temp.st[0] = num[i]; if(num[i] == ‘0‘) continue; if(!vis[mod(temp)]) { que.push(temp); vis[mod(temp)] = 1; } } //printf("%d\n", que.size()); while(!que.empty()) { State u = que.front(); que.pop(); if(mod(u) == 0) { res = u; return 1; } if(u.len>=500) continue; for(int i=0; i<M; i++) { State v = u; v.st[v.len++] = num[i]; if(!vis[mod(v)]) { que.push(v); vis[mod(v)] = 1; } } } return -1; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%d%d", &N, &C, &M); int tp = 0; for(int i=0; i<M; i++) { char s[10]; scanf("%s", s); num[tp++] = s[0]; } sort(num, num+M); /* for(int i=0; i<M; i++) printf("%c ", num[i]); printf("\n");*/ if(N == 0) { if(num[0] == ‘0‘) printf("0\n"); else printf("give me the bomb please\n"); } else { if(bfs() > 0) print(res); else printf("give me the bomb please\n"); } } return 0; }
时间: 2024-12-12 11:31:42