POJ 1465【Multiple】
描述
a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM (at least one), finds the smallest strictly positive multiple of N that has no other digits besides X1,X2..XM (if such a multiple exists).
The input file has several data sets separated by an empty line, each data set having the following format:
给你一个数字N,0<=N<=4999
再给一个数字M,代表接下来会给你M类不同的数字
希望你找出一个N的倍数出来,这个值仅由给定的M类数字构成,不包含其它的数字
希望这个N的倍数的值越小越好,如果无解输出0
输入输出格式
输入
On the first line - the number N
On the second line - the number M
On the following M lines - the digits X1,X2..XM.
输出
For each data set, the program should write to standard output on a single line the multiple, if such a multiple exists, and 0 otherwise.
An example of input and output:
输入输出样例
输入样例
22 3 7 0 1 2 1 1
输出样例
110 0
解题思路
本来呢,我开了个long long来存每次搜到的数,但是交上去,超空间???所以,机智的我用字符串来存,再写一个取余函数,边加边余,果然方便多了。然后这道题要特判0的情况,并且避免出现0000的情况,最后就出来了。
然后本题有一个剪枝的操作:举一个例子,因为36%24=12=60%24,所以36****%24=60****%24.所以我们搜到36时,记录余数,下次遇到60直接跳过就行。
题解1
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 int x[10001]; 5 bool flag[10001]; 6 int MOD(string s)//取余函数 7 { 8 int ans=0; 9 for(int i=0;i<s.size();i++) 10 { 11 ans=(ans*10+s[i]-'0')%n;//边加边余 12 } 13 return ans; 14 } 15 string bfs() 16 { 17 memset(flag,0,sizeof(flag));//初始化 18 queue<string> q;//队列 19 for(int i=1;i<=m;i++) 20 { 21 q.push(string(1,x[i]+'0'));//string(num,char)构造函数,转成字符串形式 22 } 23 while(!q.empty()) 24 { 25 string head=q.front(); 26 q.pop(); 27 if(head!="0"&&MOD(head)==0)//是倍数并且不是0 28 { 29 return head;//返回 30 } 31 for(int i=1;i<=m;i++) 32 { 33 string ans=head; 34 if(ans=="0"&&x[i]==0)continue;//避免00000 35 ans+=string(1,x[i]+'0');//加上去 36 if(!flag[MOD(ans)])//剪枝操作 37 { 38 flag[MOD(ans)]=true;//标记 39 q.push(ans); 40 } 41 else continue; 42 } 43 } 44 return "0";//没找到 45 } 46 int main() 47 { 48 while(cin>>n>>m)//循环输入 49 { 50 for(int i=1;i<=m;i++) 51 { 52 cin>>x[i]; 53 } 54 if(n==0)//特判 55 { 56 cout<<0<<endl; 57 continue; 58 } 59 sort(x+1,x+1+m);//排个序 60 cout<<bfs()<<endl; 61 } 62 }
题解2
这个的队列我用的余数,代码自己看一下,最后输出我是用了一个fa数组一步一步递归往回,最后输出。(这个没有while输入)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,sum=0; 4 struct node{ 5 int father;//父节点 6 int ans;//数值 7 }fa[10001]; 8 int num[500005]; 9 bitset<5000> flag;//bool 10 queue<int> q; 11 void put(int x) 12 { 13 if(x==0)return;//到根节点了,返回 14 put(fa[x].father);//继续向前递归 15 cout<<fa[x].ans;//打印操作 16 } 17 void bfs() 18 { 19 int l=1,r=0;//类似于手写队列,但我还是用的队列 20 for(int i=1;i<=m;i++) 21 { 22 if(num[i]!=0)//避免前导零 23 { 24 q.push(num[i]%n); 25 flag[num[i]%n]=1;//余数存储 26 r++;// 27 fa[r].father=0;//根节点 28 fa[r].ans=num[i];//记录数字 29 } 30 } 31 while(!q.empty()) 32 { 33 int head=q.front(); 34 q.pop(); 35 if(head==0) 36 { 37 put(l);//输出 38 return; 39 } 40 for(int i=1;i<=m;i++) 41 { 42 int t=head; 43 t=(t*10+num[i])%n;//继续取余 44 if(!flag[t]) 45 { 46 r++;//新建节点 47 flag[t]=1;//标记 48 fa[r].ans=num[i];//记录数字 49 fa[r].father=l;//记录father,也就是扩展它的节点的编号 50 q.push(t); 51 } 52 } 53 l++; 54 } 55 cout<<0;//没找到 56 } 57 int main() 58 { 59 cin>>n>>m; 60 for(int i=1;i<=m;i++) 61 { 62 scanf("%d",&num[i]);//输入 63 } 64 if(n==0)//特判 65 { 66 cout<<0; 67 return 0; 68 } 69 sort(num+1,num+1+m);//排序 70 bfs(); 71 }