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 }
转载于//www.cnblogs.com/hualian/p/11189568.html
还没有评论,来说两句吧...