題意:0-9這十個數字裏面的若干個數字組合出一個數,使這個數是N的倍數,求最小的這個這樣的數,不存在的話輸出-1。
按照數的位數BFS,從小向大枚舉就可以保證構造出來的數是遞增的,如果不加判斷就直接搜索的話,複雜度非常高。因此需要剪枝。
優化方法:如果一個數%N==0,那麼這個數就是N的倍數。在沒有找到的前提下,如果A%N==B%N,而且A<B,那麼其實我們就可以取A而不取B,因爲如果在A末尾增加C可以使得AC%N==0,那麼BC%N也等於0,易得:如果A和B追加數之後%N==0,那麼最優條件下追加的數肯定相同。
因此我們只需要維護組合出來的數%N的值即可,如果在搜索的途中出現了相同的%N值,就可以直接忽略了,因爲肯定沒有前面的優秀。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1000020
struct node {
int pre, mod;
char c;
} q[N];
int n, m;
bool v[10010];
void print(int x) {
if (x == 0) return ;
print(q[x].pre);
putchar(q[x].c);
}
int main() {
int cas = 1, t, a[10];
bool vis[10];
while (scanf("%d%d", &n, &m) == 2) {
memset(vis, false, sizeof(vis));
for (int i=0; i<m; i++) {
scanf("%d", &t); vis[t] = true;
}
m = 0;
for (int i=0; i<10; i++) if (!vis[i]) a[m++] = i;
printf("Case %d: ", cas++);
if (m == 0) {
puts("-1"); continue;
}
memset(v, false, sizeof(v));
int l = 1, r = 1, ans = -1;
for (int i=0; i<m; i++) if (a[i]) {
q[r].pre = 0;
v[q[r].mod = a[i] % n] = true;
q[r].c = a[i] + '0';
if (q[r].mod == 0) { ans = r; break; }
r++;
}
while (l < r && ans == -1) {
for (int i=0; i<m; i++) {
q[r].mod = (q[l].mod*10 + a[i])%n;
if (!v[q[r].mod]) {
v[q[r].mod] = true;
q[r].pre = l;
q[r].c = a[i] + '0';
if (q[r].mod == 0) { ans = r; break; }
r++;
}
}
l++;
}
if (ans == -1) puts("-1");
else {
print(ans); printf("\n");
}
}
return 0;
}