Multiple
题目链接:POJ - 1465题意:给出一个十进制数n, 和m个十进制个位数, 找出一个最小的数x, 使得x是n的倍数, 输出n;
一个新知识点: 同余剪枝;
我们先把m个十进制个位数由小到大排序, 当a<b时 若a≡b(mod n),就不再在扩展b(a小所以先扩展了a),
为什么呢, 由于a, b对n同余, 所以(a*10+i)%n ==(b*10+i)%n;, 当b后边加一个i能整除n时, 之前a一定也可以加i 整除n;也可以说之后b扩展出来的一定能由a扩展, 所以不需要再扩展b;(我们要求的是一个最小值!!!)
注意n=0时要特判;
由于最后结果可能是个大数, 所以要找个巧妙地方法存数;具体看代码;
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
int digit[15], n, m;
struct node{//now表示当前数位上是什么数, pre表示上一数位是什么数, mod表示当前数对n的余数;
int now, pre, mod;
};
int vis[5100];
vector<node> vec;
vector<int> ans;
void print(int k){
ans.clear();
while(k>=0){
ans.push_back(vec[k].now);
k=vec[k].pre;
}
for(int i=ans.size()-1; i>=0; i--){
printf("%d", ans[i]);
}
printf("\n");
}
void bfs(){
vec.clear();
node tmp;
memset(vis, 0, sizeof(vis));
for(int i=0; i<m; i++){
if(digit[i]==0) continue;//不能有前导零;因为0mod任何数都是0;
tmp.now=digit[i];
tmp.pre=-1;
tmp.mod=digit[i]%n;
vis[tmp.mod]=1;
vec.push_back(tmp);
}
int head=0;
while(head<vec.size()){
tmp=vec[head];
//printf("%d %d %d\n", tmp.now, tmp.mod, tmp.pre);
if(tmp.mod==0){
print(head);
return;
}
for(int i=0; i<m; i++){
int tmod=(tmp.mod*10+digit[i])%n;
if(vis[tmod]) continue;
node p;
p.now=digit[i];
p.pre=head;
p.mod=tmod;
vec.push_back(p);
vis[tmod]=1;
}
head++;
}
printf("0\n");
}
int main(){
while(~scanf("%d%d", &n, &m)){
for(int i=0; i<m; i++)
scanf("%d", &digit[i]);
sort(digit, digit+m);
if(n==0){
printf("0\n");
continue;
}
bfs();
}
return 0;
}