poj1426_模拟BFS

题意:给出一个200以内的数n,求出这个数的倍数M,使得M中只有0和1组成。M最多100位。

分析:这个题竟然用的是bfs的思想。不看讨论真的想不出来。思路是这样的:

1.最高位一定是1.curnum%n不为0时,说明curnum不符合要求。

2.判断curnum*10%n和(curnum*10+1)%n是否为0,不为0的话,令curnum=curnum*10和curnum*10+1继续做第二步。直到取余之后为0即可。

3.这样就会遇到大数存储的问题。可以这样解决:

令 (curnum*10+1)%n=a,求((curnum*10+1)*10+1)%m.

由定理

(a*b)%n = (a%n *b%n)%n

(a+b)%n = (a%n +b%n)%n

得((curnum*10+1)*10+1)%m=(a*10+1)%m.前一步操作得到的余数可以代替当前步的k值。

这样存储一个mod[]即可。

4.最后输出结果。比如求6的倍数。

用数组mod[]存储余数,其中mod[0]不使用,由mod[1]开始

那么mod中的余数依次为: 1 4 5 4 5 2 3 4 5 2 3 2 3 0  共14个

令i=14,通过观察发现,i%2恰好就是 6 的倍数的最低位数字

i/2  再令 i%2 ,恰好就是 6 的倍数的 次低位数字。。。

循环这个操作,直到i=0,就能得到 6的 01倍数(一个01队列),倒序输出就是所求

这样就完成了 *10操作到 %2操作的过渡。

代码

View Code
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <memory.h>
 4 using namespace std;
 5 
 6 const int maxnum=524286;  //这个数字是找的网上的。
 7 int mod[maxnum];
 8 
 9 void digui(int m)
10 {
11     if(m==0) return ;
12     digui(m/2);
13     printf("%d",m%2);
14 }
15 
16 int main()
17 {
18     int m,cnt;
19     while(scanf("%d",&m)!=EOF)
20     {
21         if(m==0) break;
22         memset(mod,0,sizeof(mod));
23         cnt=1;
24         mod[cnt]=1;
25         cnt++;
26         while(1)
27         {
28             mod[cnt]=mod[cnt/2]*10%m;  //模拟bfs
29             if(mod[cnt]==0) break;
30             cnt++;
31             mod[cnt]=(mod[cnt/2]*10+1)%m;
32             if(mod[cnt]==0) break;
33             cnt++;
34         }
35         digui(cnt);  //递归比较费时间。
36         printf("\n");
37     }
38     return 0;
39 }
posted @ 2012-07-30 09:03  pushing my way  阅读(219)  评论(0编辑  收藏  举报