连载5:寻找符合条件的整数(《编程之美》第2.8节)

该博客介绍了《编程之美》第2.8节的问题,即寻找一个最小的正整数M,使得N * M的十进制表示仅含1和0。文中给出了三种解法:二叉树搜索、试乘法和分级组合法,并讨论了针对大数字的优化策略,如深度优先搜索和启发式搜索。
摘要由CSDN通过智能技术生成

问题

    《编程之美》第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
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值