您的位置:首页 > 其它

约瑟夫问题,过程推理,递归

2017-07-22 12:35 211 查看
约瑟夫问题描述:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列,(来自百度百科)。一般题会让我们求出最后一个人几号;

先举一个简单的例子吧:  

                                                                           

如上图从1到10围城的圆圈,没个一个数去掉一个,问最后那个数被留了下来;

我们可以简单模拟一下期初先消去2,依次为:4,6,8,10,3,7,1,9,于是最后剩余了5号,

我们可以设T
表示当有n个数围城一个圈,最后剩余的那个数就是T
,然后我们开始模拟,推理。


先把n(1...10)给推出来吧:

         

可以看出来T
总是奇数,因为我们在绕第一圈的时候就已经把所有的偶数给去掉了,不信自己可以模拟一番,


既然第一轮去掉的都是偶数,那么我们可以利用这个结论,假如我们假设有2n个数,经过第一轮去掉之后,那么毋庸置疑就只剩下奇数了,那么3号就是第二轮的第一个要去掉的。而T[2n]又可以由T
这个过程推出来,2n的第二轮开始的数就相当于n的第一轮开始的数的二倍减一,依次类推我们可以得出:T[2n]=2T
-1;


我们可以根据这个推论快速推出T[20]=  2*T[10]-1  =  2x5-1  =  9;

但是我们并没有推出更为简单的结果,并不满意,我们根据找出来的这个规律再写出多一点例子:



乍一看,这么多数哪有什么鬼规律,其实仔细一看还是有的,有一个递增(d=2)的循环节数列,为了容易分辨请看下表,每组循环节我用不同的颜色给标记了:



<
e00b
strong>神奇吧,然后我们再来推论,T
(n->+oo)的情况;[/b]

我们要推出这个循环节出现的情况,然后对应每个单独的循环节求值,就简单了。

然后我们开始讨论循环节,(这里说循环节可能不合适,但是我没有找到一个合适的词语形容,大家知道我要表达的意思就好,怪我才疏学浅),我们以n为例;

第一个循环节:1

第二个循环节:2,3

第三个循环节:4,5,6,7

第四个循环节:8,9,10,11,12,13,14,15

第五个循环节:16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31

.......

有没有发现,每个循环节都是以一个2的次方开始并且以一个2的次方减一结束,如:

第一个循环节是:[2^0,2^1),          (左闭右开哦)

第二个循环节是:[2^1,2^2),

第三个循环节是:[2^2,2^3),

......

第N个循环节是:[2^(N-1),2^N);

聪明的小伙伴想必现在已经有答案了,但是鄙人眼拙,还要做一下计算,回归一开始的T


那么现在当n=6时,我们可以直接找到开始的循环节是4,所以n=6是在本循环节的m=(6-4+1)=3位,再用等差数列求和公式即:T[6]=   d*(m-1)+1   =2*2+1=5;

同样的当n=100时,我们可以立刻求出,实在64循环节的(100-64+1)=37位,然后T[100]=2*36+1=73;

然后一般式就是:  
T
= 2*(n-m)+1;
(m可由上述的n=100或者n=6的出)


注:m要根据n来定,可以存一个数组,因为2的32次方已经超大了,所以不会影响时间复杂度;

那么现在这个问题已经解决了,但是关于这个问题还有一个更加神奇的推广(我从一本神奇的书上看到过),有兴趣的小伙伴可以继续往下看:

在求解的过程中,我们发现2的幂起了很重要的作用,所以自然要来研究n和T
的以2为基数的表示即二进制。





然后经过一系列的转化......具体的过程我忘了,我只记住了结果,就是n的二进制,最高位的那个数放到最低位,比如n=6时,n=(110)₂,然后我们把最高位放到最后得n=(101)₂,然后再算二进制,1*2^2
+ 0*2^1 + 1*2^0 = 5;


显然答案是对的,再举个例子吧,当n100时,[b]n=(1100100)₂,然后最高位的1放在最后得:[b]n
 =  (1001001)₂;
[/b][/b]

[b][b]最后结果经过计算得:64+8+1  =  73;   可以证明答案是对的,所以我们可以套上面的公式,也可以用二进制的方法求解;[/b][/b]

[b][/b]

[b]也许你对上面的解释有疑问,就是为什么要把二进制的最高位放在最后呢,这个我也没法对你做出正规的解释,但是我又找到了另一个不改变最高位的方法,还拿n=6时为例吧,[b]n=(110)₂
= 1*2^2 + 1*2^1 - 1*2^0 = 4 + 2 - 1 = 5;
[/b][/b]

[b]再如:n=100时,[b]n=(1100100)₂=2^6
+ 2^5 - 2^4 - 2^3 + 2^2 - 2^1 - 2^0 =64+32-16-8+4-2-1 = 73;
[/b][/b]

这个结果是对的,也不需要进行二进制最高位的转换,所以我们可以得出T
结果就是n的对应二进制,位为1就加位为0就减
,这个结果就很容易算出来了,虽然很神奇,但是我还是比较喜欢我的推出来的那个解法;


当然我相信约瑟夫还有后续,还有很长的路,但是我不能就此止步,去学更多新知识了;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: