今天闲着无聊整理下《具体数学》中关于约瑟夫问题的讨论。
n个人围成一圈,从
1 到n标号,每隔一个人处死一个人,求最后幸存下来的人的编号,例如n=10 ,则被杀的人按顺序依次是:2,4,6,8,10,3,7,1,9
当然可以直接模拟杀人的过程直到剩下最后一个,但这种方法不够快。
可以考虑递归做法,如果杀了一圈,那么这个时候我们可以把剩下的人从1开始重新排列,这样如果能够找到两次排列的编号关系,就可以用递归来解决了。
假设
以n=10为例,
杀之前: [1,2,3,4,5,6,7,8,9,10]
杀之后: [1, ,2, ,3, ,4, ,5, ]
其中空出来的表示在这轮中阵亡的。
可以很轻松的发现这两者之间的关系(∗2−1),因此我们可得:
假设J(n)为n个人的约瑟夫环最后剩下的幸存者的编号,因此有
J(2n)=2J(n)−1
同理如果是奇数呢
以n=9为例,
杀之前: [1,2,3,4,5,6,7,8,9]
杀之后: [ , ,1, ,2, ,3, ,4]
其中空出来的表示在这轮中阵亡的。
因此,我们也可以得到他们之间的关系:(∗2+1),所以有:
J(2n+1)=2J(n)+1
因此合起来我们可以得到递推式:
J(2n)=2J(n)−1
J(2n+1)=2J(n)+1
当n=1时,则有J(n)=1
接下来求J(n)的闭形式:
根据J(2n)=2J(n)−1,且J(1)=1可得,J(2m)=1恒成立,因此假设对于所有的数都能表示为2m+l,0≤l<2m,则有
J(2m+l)=2l+1
这是因为,如果杀了l个人,此时,剩下的人数则为2m 个,因此,此时幸存的人应该是第l个被杀的人的后一个,因此也就是2l+1 。
在书中,作者是用了猜想+数学归纳法的方法来证明这个式子的,之后他发现了一个有趣的模式:
如果用二进制表示递推式,可得:
n=(1bm−1bm−2...b1b0)2
l=(0bm−1bm−2...b1b0)2
2l+1=(bm−1bm−2...b1b01)2
因此最后可得:
J((bmbm−1...b1b0)2)=(bm−1...b1b0bm)2
也就是将人数n的二进制形式向左循环移动一位,就可以得到幸存的人的编号,通过这也就可以得出如果当人数为
接下来拓展一下,可以解决形如:
f(1)=α
f(2n+j)=2f(n)+βj
其中j=0,1,n≥1
的问题:
假设n=(bmbm−1...b1b0)2
则可以不断把最后一位提出来:
f((bmbm−1...b1b0)2)=2f((bmbm−1...b1)2)+βb0
…
…
=2mα+2m−1βbm−1+...+2βb1+βb0第一位是α的原因在于bm=1。
于是就有了如下的结论:
f(bmbm−1...b1b0)2=(αβbm−1βbm−2...βb1βb0)2
回到约瑟夫问题,这是当α=1,β0=−1,β1=1时的特例,可以发现,当n写成
例如,当n=100时,有n=(1100100)2,因此可以分解成三段:(1)2,(100)2,(100)2,而每段变换后分别得到(1)2,(001)2,(001)2,合起来后变成(1001001)2,也就相当于进行了向左循环移位。
当然我们可以再弱化一下递归式,变成:
f(j)=αj, 1≤j<d
f(dn+j)=cf(n)+βj, 0≤j<d,n≥1
我们同样可以假设此时的n可以表示为
f((bmbm−1...b1b0)d)
=cf((bmbm−1...b1)d)+βb0
=c2f((bmbm−1...b2)d)+cβb1+βb0
...
=cmαbm+cm−1βbm−1+...+cβb1+βb0
=(αbmβbm−1βbm−2...βb1βb0)c
即f((bmbm−1...b1b0)d)=(αbmβbm−1βbm−2...βb1βb0)c
所以遇到这种类型的递归式,只需要做进制数的改变就行了。
例如,有递归式
f(1)=34
f(2)=5
f(3n)=10f(n)+76,(n≥1)
f(3n+1)=10f(n)−2,(n≥1)
f(3n+2)=10f(n)+8,(n≥1)
且我们要求解f(19),因为d=3,c=10,因此,
博客探讨了约瑟夫问题的解决方案,包括递归公式J(2n)=2J(n)-1和J(2n+1)=2J(n)+1,并通过二进制表示揭示了幸存者编号的循环移位规律。此外,还讨论了如何将这种方法拓展到更一般的形式f(n),并给出了其他递归式的解题思路。

532

被折叠的 条评论
为什么被折叠?



