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

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

POJ 1426 - Find The Multiplehttp://poj.org/problem?id=1426


题目要求:

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


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

示例:

Input

2
6
19
0

Output

10
100100100100100100
111111111111111111

 

非常容易想出从1开始搜索,然后是1011,进而为100101110111,等等。

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

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

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

 

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

一开始是1,它有两个子节点1*101*10+1,入队。队列里只有1011

然后就是10,子节点10*1010*10+1,入队。队列有11100101

11,子节点11*1011*10+1,入队。队列有100101110111……


在父层未搜索完之前,各个子节点是处于等待的状态的。这就保证了父层优先被遍历,也就是所谓的宽度优先搜索(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 }

 

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

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


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


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

另一个程序把这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 }

 

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

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


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

 

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

 

输出程序:

 

 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     

 

如果你把这个打表改成这样去提交是会超时的。想想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 }
View Code

 

 

 

 

 

这里是本题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 }
View Code

 

posted @ 2019-02-17 19:16  Kaidora  阅读(291)  评论(0编辑  收藏  举报