答案会爆long long ,所以要逐位搜索。即每一次向最后插一个数。然后判断这个数是不是N的倍数。
搜索时有一个重要的剪枝,对于数N,他有N个剩余类( 余数为0到N-1), 这些剩余类是等价的,而且最优的就是这个剩余类中最小的数。
例: a 和 b 模 n 都等于m ,那么(a*10+k ) mod N 等于(b*10+k)mod N 等于 k。
所以维护每个剩余类是从哪个剩余类构造过来的,和构成这个数时加的那一位是什么数。
然后搜到这个数后递归输出,保证是逆序的。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
#define maxn 10005
int rem[maxn];
int last[maxn];
bool a[10];
int N;
int kase=1;;
void show(int n){
if(rem[n]!=-1){ show(rem[n]);}
printf("%d",last[n]);
}
void bfs(){
queue<int > Q;
for(int i=1;i<10;i++){
if(a[i]) continue;
int t=i%N;
last[t]=i;
if(t==0){
printf("Case %d: %d\n",kase++,i);
return ;
}
Q.push(t);
}
while(!Q.empty()){
int cur=Q.front();
Q.pop();
for(int i=0;i<10;i++){
if(a[i]) continue;
int tmp=(cur*10+i)%N;
if(last[tmp]==-1){
rem[tmp]=cur;
last[tmp]=i;
Q.push(tmp);
}
if(tmp==0){
printf("Case %d: ",kase++);
show(tmp);
printf("\n");
return ;
}
}
}
printf("Case %d: -1\n",kase++);
}
int main(){
int M;
while(~scanf("%d%d",&N,&M)){
memset(rem,-1,sizeof(rem));
memset(last,-1,sizeof(last));
memset(a,0,sizeof(a));
for(int i=1;i<=M;i++){
int tmp;
scanf("%d",&tmp);
a[tmp]=1;
}
bfs();
}
return 0;
}