[题解] [BFS] POJ 1426 - Find The Multiple

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

VJudge题目:https://cn.vjudge.net/contest/279018#problem/L

即POJ 1426 - Find The Multiple:http://poj.org/problem?id=1426

题目要求:

给出一个不大于200的整数n,要求找到任意一个n的倍数(十进制),并且这个倍数只由1与0组成,最多100位。

输入输出:输入以0结束。

示例:

Input:

2
6
19
0

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

Output:

10
100100100100100100
111111111111111111

非常容易想出从1开始搜索,然后是10与11,进而为100、101、110、111,等等。

如果你知道二叉树,这图你一定见过,这里我画了一个二进制版本。把这些数字看成十进制,所有1与0组成的数都在这树中。

这棵树是无限高的,虽然题目限制了100层,但是也不能用DFS去做。

比如输入一个3,这里最小的倍数是111,但是假如你写的BFS优先查找左节点,一直搜索到1e100(100层)也没有遇到3的倍数,就会浪费很多时间。因此此处要一层一层地搜索。

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

虽然我这里搬出了二叉树的图,但是此处并不需要建树。你需要的仅仅只是一个队列。想象一下搜索过程:

一开始是1,它有两个子节点1*10、1*10+1,入队。队列里只有10和11;

然后就是10,子节点10*10、10*10+1,入队。队列有11、100、101;

11,子节点11*10、11*10+1,入队。队列有100、101、110、111……

在父层未搜索完之前,各个子节点是处于等待的状态的。这就保证了父层优先被遍历,也就是所谓的宽度优先搜索(BFS)。

知道怎么做后代码应该很容易写出来。至于队列怎么写,此处只能用C++
STL提高的queue。

100位数字怎么存?这个先不要管,直接用long
long,因为最大也就19位数。

代码如下:

 1 #include <cstdio>
 2 #include <string>
 3 #include <stdlib.h>
 4 #include <queue>
 5 using namespace std;
 6 queue <long long> que;
 7 int cleanQueue()
 8 {
 9     while(que.size())
10     {
11         que.pop();
12     }
13 }
14
15 int main()
16 {Start:;
17     int N;
18     scanf("%d",&N);
19     if(N==0)return 0;
20     cleanQueue();
21     que.push(1);
22     long long tmp;
23     while(1)
24     {
25         tmp=que.front();    que.pop();
26         if( tmp%N==0)
27         {
28             printf("%lld\n",tmp);
29             break;
30         }
31         else
32         {
33             tmp=tmp*10;
34             que.push(tmp);que.push(tmp+1);
35         }
36     }
37     goto Start;
38 }

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

我不怎么会用C++,本来自己写的C队列没啥毛病OJ说超内存(本题限10000KB)。我不知道是不是因为calloc申请来的地址太大的缘故。

这沙雕C++编译器还逼我在calloc前写指针转换,C编译器反而不会,神奇。

至于为什么可以直接用long
long,因为有种操作叫打表。先把200个数各自的倍数找出来,提交给OJ的程序直接把答案报出来就完了。

打表就是先写一个程序,把从1到200每个数的倍数找到,输出为文本;

另一个程序把这200个倍数放入long
long answer[202]数组,按下标输出答案。

在此之前你并不知道数字有多大,先按题目要求搞一个100位大数。然后在本地类似地BFS就行了。

大数写得太丑运算量挺大的,随便超时。不然怎么要本地打表?

代码如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3     short bin[102]={0};
 4
 5 int main()
 6 {
 7     int p1();    int div(int base);    int printanswer();
 8     for(int base=1;base<=200;base++)
 9     {
10         memset(bin,0,102*sizeof(short));
11         while(1)
12         {
13             p1();
14             if(div(base)==0)
15             {
16     //            printf("%d,",base);
17                 printanswer();
18                 break;
19             }
20         }
21     }
22     return 0;
23 }
24
25 int p1()
26 {
27     int bit=101;
28     bin[101]+=1;
29     while(1)
30     {
31         if(bin[bit]==2)
32         {
33             bin[bit]=0;
34             bit--;
35             bin[bit]+=1;
36         }
37         else break;
38     }
39 }
40
41 int div(int base)
42 {
43     int remain=0;
44     int last;
45     for(int i=0;i<102;i=i+3)
46     {
47         last=remain*1000+bin[i]*100+bin[i+1]*10+bin[i+2];
48         remain=last%base;
49     }
50     if(remain)return 1;
51     else return 0;
52 }
53
54 int printanswer()
55 {
56     int i=0;
57     for(;i<102;i++)
58     {
59         if(bin[i])break;
60     }
61     for(;i<102;i++)
62         printf("%d",bin[i]);
63
64     printf(",");
65 }

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

把输出的’,’换为换行,看看是不是最高19位数。

其实,11行这里不把大数重置为0也行,毕竟总会有更大的倍数存在。

导出到输出程序:(你要在终端复制过去也行)

./a.out >> L_Print.c	//一个>覆盖文本,两个>>追加文本。空文件随意。

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

输出程序:

 1 #include <stdio.h>
 2
 3 long long answer[202]={0,1,10,111,100,10,1110,1001,1000,111111111,10,11,11100,1001,10010,1110,10000,11101,1111111110,11001,100,10101,110,110101,111000,100,10010,1101111111,100100,1101101,1110,111011,100000,111111,111010,10010,11111111100,111,110010,10101,1000,11111,101010,1101101,1100,1111111110,1101010,10011,1110000,1100001,100,100011,100100,100011,11011111110,110,1001000,11001,11011010,11011111,11100,100101,1110110,1111011111,1000000,10010,1111110,1101011,1110100,10000101,10010,10011,111111111000,10001,1110,11100,1100100,1001,101010,10010011,10000,1111111101,111110,101011,1010100,111010,11011010,11010111,11000,11010101,1111111110,1001,11010100,10000011,100110,110010,11100000,11100001,11000010,111111111111111111,100,101,1000110,11100001,1001000,101010,1000110,100010011,110111111100,1001010111,110,111,10010000,1011011,110010,1101010,110110100,10101111111,110111110,100111011,111000,11011,1001010,10001100111,11101100,1000,11110111110,11010011,10000000,100100001,10010,101001,11111100,11101111,11010110,11011111110,11101000,10001,100001010,110110101,100100,10011,100110,1001,1111111110000,11011010,100010,1100001,11100,110111,11100,1110001,11001000,10111110111,10010,1110110,1010100,10101101011,100100110,100011,100000,11101111,11111111010,1010111,1111100,1111110,1010110,11111011,10101000,10111101,111010,1111011111,110110100,1011001101,110101110,100100,110000,100101111,110101010,11010111,11111111100,1001111,10010,100101,110101000,1110,100000110,1001011,1001100,1010111010111,110010,11101111,111000000,11001,111000010,101010,110000100,1101000101,1111111111111111110,111000011,1000};
 4
 5 int main()
 6 {Start:;
 7     int N;
 8     scanf("%d",&N);
 9     if(N==0)return 0;
10     printf("%lld\n",answer[N]);
11     goto Start;
12 }
13     

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

如果你把这个打表改成这样去提交是会超时的。想想long long是系统提供的整数,比自己写的渣渣大数不知道高哪里去了。

 1 #include <stdio.h>
 2 #include <string.h>
 3     short bin[102]={0};
 4
 5 int main()
 6 {
 7     int N;
 8     int p1();    int div(int base);    int printanswer();
 9     Start:;
10     scanf("%d",&N);
11     if(N==0)return 0;
12 //    for(int base=1;base<=200;base++)
13 //    {
14         memset(bin,0,102*sizeof(short));
15         while(1)
16         {
17             p1();
18             if(div(N)==0)
19             {
20     //            printf("%d,",base);
21                 printanswer();
22                 break;
23             }
24         }
25 //    }
26     goto Start;
27 }
28
29 int p1()
30 {
31     int bit=101;
32     bin[101]+=1;
33     while(1)
34     {
35         if(bin[bit]==2)
36         {
37             bin[bit]=0;
38             bit--;
39             bin[bit]+=1;
40         }
41         else break;
42     }
43 }
44
45 int div(int base)
46 {
47     int remain=0;
48     int last;
49     for(int i=0;i<102;i=i+3)
50     {
51         last=remain*1000+bin[i]*100+bin[i+1]*10+bin[i+2];
52         remain=last%base;
53     }
54     if(remain)return 1;
55     else return 0;
56 }
57
58 int printanswer()
59 {
60     int i=0;
61     for(;i<102;i++)
62     {
63         if(bin[i])break;
64     }
65     for(;i<102;i++)
66         printf("%d",bin[i]);
67
68     printf("\n");
69 }

这里是本题C队列的简单实现,仅供参考:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4
 5 struct LLQueue
 6 {
 7     long long bin;
 8     struct LLQueue *next;
 9 }head;
10 struct LLQueue *front=&head;
11 struct LLQueue *back=&head;
12 int push(long long in)
13 {
14     back->next = calloc(1,sizeof(struct LLQueue));
15     back=back->next ;
16     back->bin = in ;
17     back->next= 0 ;
18     if(front==&head)
19     {
20         front=back;
21         head.next=0;
22         return 1;
23     }
24     return 1;
25 }
26 int pop()
27 {
28     struct LLQueue *p=front;
29     if(front!=back)
30     {
31         front=front->next;
32         free(p);
33         return 1;
34     }
35     else if(front!=&head)
36     {
37         front=back=&head;
38         free(p);
39         return 0;
40     }
41     else return 0;
42 }
43 int cleanQueue()
44 {
45     while(pop());
46 }
47
48
49
50 int main()
51 {Start:;
52     int N;
53     scanf("%d",&N);
54     if(N==0)return 0;
55     cleanQueue();
56     push(1);
57     long long tmp=front->bin;
58     while(1)
59     {
60         tmp=front->bin;
61         if( tmp%N==0)
62         {
63             printf("%lld\n",tmp);
64             break;
65         }
66         else
67         {
68             tmp=tmp*10;
69             push(tmp);push(tmp+1);
70             pop();
71         }
72     }
73     goto Start;
74 }

p { margin-bottom: 0.25cm; line-height: 115% }
a:link { }

原文地址:https://www.cnblogs.com/Kaidora/p/10392293.html

时间: 2024-07-28 21:27:45

[题解] [BFS] POJ 1426 - Find The Multiple的相关文章

BFS/poj 1426 Find The Multiple

1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 int n; 6 bool v[210]; 7 unsigned long long bfs(int n) 8 { 9 memset(v,0,sizeof(v)); 10 queue<unsigned long long>que; 11 unsigned long long now,next; 1

DFS/BFS(同余模) POJ 1426 Find The Multiple

题目传送门 1 /* 2 题意:找出一个0和1组成的数字能整除n 3 DFS:200的范围内不会爆long long,DFS水过~ 4 */ 5 /************************************************ 6 Author :Running_Time 7 Created Time :2015-8-2 14:21:51 8 File Name :POJ_1426.cpp 9 ******************************************

POJ 1426 Find The Multiple(寻找倍数)

p.MsoNormal { margin-bottom: 10.0000pt; font-family: Tahoma; font-size: 11.0000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: left; font-family: 宋体; font-weight: bold; font-size: 24.0000pt } span.10 { font-family: "Times New Rom

广搜+打表 POJ 1426 Find The Multiple

POJ 1426   Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25734   Accepted: 10613   Special Judge Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representati

20200202 POJ - 3126 Prime Path POJ - 1426 Find The Multiple

>>>>>>>>>POJ 1426直达?? >>>>>>>>>POJ 3126直达?? 做了这么几道搜索题,感觉差不多也摸出了门路,模板差不多记下来了,只是面对不同的题目算法不同罢了 简单写一下想法,搞明白搜索的主题到底是什么(之前的mutiple那题,一开始就没想明白到底搜谁,就没想到算法 TBC(晚上再写 ===================================分割线=======

POJ 1426 - Find The Multiple - [DP][BFS]

题目链接:http://poj.org/problem?id=1426 Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a correspo

(简单) POJ 1426 Find The Multiple,BFS+同余。

Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no mo

poj 1426 Find The Multiple (bfs 搜索)

Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18012   Accepted: 7297   Special Judge Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains

POJ 1426 Find The Multiple(DFS,BFS)

Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100