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 }