猫吃老鼠

来源:互联网 发布:好看的战争小说 知乎 编辑:程序博客网 时间:2024/04/28 07:24

问题描述
    现有n个老鼠围成一圆圈,有一只猫从编号为1 的位置开始吃老鼠,每次都隔一个老鼠吃,请给出最后一个老鼠的编号?题目要求是任给老鼠数i,输出猫最后吃的老鼠的编号。

 

这个问题常见的解法是建链表遍历或数组设标志。 用这些方法的都是好同学。。

 

都知道的事多说无意。  看看我的猫儿是如何抓到这最后一只老鼠的。。

 

先看源码

 

int
my_cat(int i)
{
 int a = 1;
 
 while(a*2<i)  a*=2;

 if(a != i)  a = (i-a)*2;


 return a;
}

源码ok.

 

 1    先说说源码做了什么。

 

        while 循环,将a 置为与老鼠总数 i 的位数相同,以备后用。  这里的位数是指 二进制位数。

        if语句 计算 最后老鼠的编号。

        

        看到这里,我也不清楚为啥就算出来了呢?  不过,可以肯定的是,和二进制相关。。。

 

2    因为所以

 

      将问题转化一下,或许更好理解。

 

      猫想吃老鼠了,命令老鼠们按高矮个排好,报数。 1,2,3,4。。。。。。。。。

      单数的向前一步,吃掉。 双数的养起来。

       这是第一顿。

 

      日上三杆,猫又饿了。 命令老鼠排队报数。1,2,3,。。。。

       这次吃单数双数呢?  

      猫想了想,上次报的总数的是单数的话,这次就吃双数的; 是双数的话,这次就吃单数的。

      于是,猫又吃了一顿。

      这是第二顿。

 

      夕阳西下。

      猫开始了第三顿,还是老规矩,排队报数,单双数规矩和上一顿一样。

      第三顿over.

        

     一顿一顿又一顿。

 

     最后,还剩一只老鼠, 这只最长寿的老鼠一开始排第几?

 

     为了让大家明白这个因为所以,让猫儿再吃一遍。

 

    第一顿, 单数吃掉, 留下的老鼠的编号只有双数,也就是说,编号的二进制的最低位是 0。

                    (i-a)*2中乘2 后正好最低位是0。

                    吃完后老鼠的总数是 吃前总数数值右移一位。

 

    第二顿, 留下单数还是双数与前一顿吃之前的总数有关。 是双数就留下双数的,是单数就留下单数的。

                    前一顿吃之前的总数正好是老鼠的总数。单双数取决于二进制的最低位。

                    因此,幸存老鼠的编号的倒数第二位 与 老鼠的总数的倒数第一位 相同。

 

    

    第三顿, 留下单数还是双数与前一顿吃之前的总数有关。 是双数就留下双数的,是单数就留下单数的。

                    前一顿吃之前的总数是 第一顿吃完后的老鼠总数,单双数取决于二进制的最低位,也就是一开始老鼠总数的倒数第二位。

                    因此,幸存老鼠的编号的倒数第三位 与 老鼠的总数的倒数第二位 相同。

    。。。。。。。

    最后一顿之前,此时幸存的老鼠就是最后的一只老鼠了(不要问我为什么)。 它的编号也就已经确定了。

                    最后一位是0,到数第二位与老鼠的总数的倒数第一位 相同,到数第三位与老鼠的总数的倒数第二位 相同,,,,。

                    此时,老鼠总数是1,也就是开始时老鼠总数的最高位,程序中的a 。 该位不在长寿老鼠的编号中,所以a = (i-a)*2。

 

    以上方法,对于老鼠总数是 2的幂次时,结果为0。第0只老鼠??   那就是最后一只了。因为猫是绕着圈吃的。   @。@!!

 

看着猫儿大吃,我也饿了。。。

不要误会,  我不吃老鼠啊。

 

    

 

        

原创粉丝点击