问题
《编程之美》第2.8节:任意给定一个正整数N,求一个最小的正整数M(M >1),使得N * M 的十进制表示形式里只含有1 和0,例如:
1 * 1 = 1 2 * 5 = 10
3 * 37 = 111 4 * 25 = 100
5 * 2 = 10 6 * 185 = 1,110
7 * 143 = 1,001 8 * 125 = 1,000
9 * 12,345,679 = 111,111,111
解法一
既然乘积是类似101011…的形式,那么可以使用二叉树去遍历所有乘积,从小到大,直到找到满足条件的。例如,下图是N=3 时搜索的情况:
需要说明的是,在搜索二叉树的同一层中,相同余数的节点以后 发展出来的节点余数也是相同的(若X≡Y (mod N),则X*10≡Y *10 (mod N) X*10+1≡Y *10+1 (mod N)),所以只需要保留一个节点即可。
关键代码如下:
var remainders = new int[n]; //设置一个数组来保存每层的余数(N 的余数个数≤N) var queue = new Queue<BigInt>(); //设置一个队列来实现分层搜索二叉树 queue.Enqueue((BigInt)1); while (queue.Count > 0) { var v = queue.Dequeue(); var r = v % n; if (r == 0) { Console.WriteLine("{0} * {1} = {2}", n, v / n, v); break; } if (remainders[r] == v.Digit) continue; else remainders[r] = v.Digit; v *= 10; que