题目大意:给定 n个数字 其中若干组合(可以重复)成一数 x, 使得xmod m=0,且x 最小
思想:一,假设 有数 1,2,3 显然应从小到大枚举这3个数字构成的数,当然数会很大,高精度
1,2,3
11,12,13,
111,112,113,
121,122,123,
.............................
通过上述例子,可以看出完全是队列的性质。
二,数构造出来后去对m求余的过程可不可以优化呢?
肯定是可以的。
(a+b)%m=(a%m+b%m)%m;
(a*10+b)%m=((a%m)%10+b)%m 就是用这个性质
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <stack>
#include <map>
#include <queue>
using namespace std;
struct num{ //结构题保存构造的数
int re; //这个数除m的余数
string strnum; //高精度保存大数
};
int digit[10];
int n;
int remand[5000]; //remand[i]=1 表示mod m 余数为i 存在
int main(){
int i,j,k,m,x;
while(cin>>n){
cin>>m;
for(i=0;i<m;i++)
scanf("%d",&digit[i]);
if(n==0){
printf("0\n");
continue;
}
memset(remand,0,sizeof(remand));
queue<num>q;
sort(digit,digit+m); //保证枚举的数从小到大
num b,temp,ans;
b.re=0;
b.strnum="";
q.push(b); //第一个插入0
while(!q.empty()){
temp=q.front();
q.pop();
for(i=0;i<m;i++){
x=temp.re*10+digit[i]; //构造新数
if(x==0)
continue; //如果这几个数中有0 ,不需再查
if(!remand[x%n]){ //新数产生新的对m的余数 才放进队列 ,因为数是有小到大生成的,保证数最小。
remand[x%n]=1; //保存余数
ans.re=x%n;
ans.strnum=temp.strnum;
ans.strnum+=char(digit[i]+'0'); //存储大数
q.push(ans); //加入队列
}
if(remand[0]){ //判断余数0第一次出现
cout<<ans.strnum<<endl;
goto Over; //goto 语句是很有用的,双重循环,避免标记。
}
}
}
printf("0\n"); //队列空了也没找到,就是找不到了。
Over:; //:后要有语句,当然空语句也可以
}
return 0;
}