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; }