约瑟夫问题
约瑟夫斯置换是一个出现在计算机科学和数学中的问题。在计算机编程的算法中,类似问题又被称为约瑟夫环。
人们站在一个等待被处决的圈子里。 计数从圆圈中的指定点开始,并沿指定方向围绕圆圈进行。 在跳过指定数量的人之后,处刑下一个人。 对剩下的人重复该过程,从下一个人开始,朝同一方向跳过相同数量的人,直到只剩下一个人,并被释放。
问题即,给定人数、起点、方向和要跳过的数字,选择初始圆圈中的位置以避免被处决。
—— 来自Wikipedia
问题假设
为了方便研究,我们设最开始的总人数为n
,每次跳过的人数为k
,并且人的编号从0开始。
对于递推公式的证明,本文推广到了跳过人数k
为任意值的情况;对于非递推公式,由于过于复杂,所以只能证明到k=2
的情况。
递推公式证明
假设编号从0开始,现证明约瑟夫问题的递推公式为:
J(n)={0, n=1(J(n−1)+2)modn
考虑有n个人的情况,则这些人编号为0,1,2,⋯,n−1。则当报数为2的人,即1号被杀掉时,这些人编号依次为0,2,3,⋯,n−1,则可以把问题从n的规模减少到n-1。此时还需继续报数,由于约瑟夫问题是按环报数的,所以我们可以把之前报过数的人重新安排到序列的末尾,则现在的编号依次为:2,3,4,⋯,n−1,0。
如果我们将这些人序号限制在大小为n的群上,则被重新排列到末尾的人i也可以被编号为i+n。那么此时的编号即为2,3,4,⋯,n−1,n。依此类推,可以把规模为n的情况转化为规模为1的情况,但是需要推理编号的关系。
原n-1情况下编号为0,1,2,⋯,n−1,由n情况下递推回去的编号为2,3,4,⋯,n−1,n,则可以推出一般情况下的递推公式为(J(n−1)+2)modn。
不失一般性,但约瑟夫问题报数的轮次为k时,可以用同样的证法证明,递推公式为:
J(n)={0, n=1(J(n−1)+k)modn
非递推公式证明
当k=2时,约瑟夫问题的非递推公式为
J(n)=2(n−2⌊log2n⌋)
证明如下:
使用数学归纳法,当n=1时,有J(1)=0,n=2时,有J(2)=0,显然成立。
假设上述公式对于n=i, i≥1成立,即:
J(i)=2(i−2⌊log2i⌋)
则当n=i+1时:
若i+1=2k, k∈N,此时⌊log2i⌋=k−1,⌊log2i+1⌋=k,根据递推公式:
J(i+1)=(J(i)+2) =2(i−2⌊log2i⌋)+2=2(2k−1−2k−1)+2=2k=0=2(i+1−2⌊log2i+1⌋)modi+1modi+1modi+1modkk
若i+1=2k,k∈N,我们可以假设2k−1≤i<2k,则⌊log2i⌋=k−1,⌊log2i+1⌋=k−1,根据递推公式:
J(i+1)=J(i)+2=2(i−2⌊log2i⌋)+2=2(i−2k−1)+2=2(i+1−2⌊log2i+1⌋)=2(i+1−2⌊log2i+1⌋)modi+1modi+1modi+1modi+1
所以综上所述,若当n=i时非递推公式成立,则n=i+1时非递推式也成立。
证毕。