约瑟夫环:围成一圈,数到几就出局

n个人围圈,从某处起每数到第k个就杀掉,问最后活下来的站在哪。k=2时有神奇函数 J(n)=2L+1。

分类
组合游戏
难度
进阶
标签
约瑟夫环、递推、位运算、游戏
约瑟夫环:围成一圈,数到几就出局 · 漫画配图
漫画 · 约瑟夫环:围成一圈,数到几就出局

题目

nn 个人围成一圈,编号 1 到 nn。从 1 号开始,每数到 2 的人出局(杀 2、4、6……绕圈继续),剩下的人重新接续计数。最后活下来的那个人,原位号是多少?

例如 n=7n=7:出局顺序 2,4,6,1,5,3,幸存者是 7 号。

答案与解析

k=2k=2 时,幸存位置有漂亮公式。把 nn 写成 n=2m+Ln = 2^m + L0L<2m0\le L<2^m),则 J(n)=2L+1J(n) = 2L + 1

例如 n=7=4+3n=7=4+3,则 J=2×3+1=7J=2\times3+1=7n=41=32+9n=41=32+9,则 J=2×9+1=19J=2\times9+1=19

推导思路(递推):设 f(n)f(n)nn 人时幸存者(从 1 起)。第一圈杀掉所有偶数,剩下奇数 1,3,5,1,3,5,\dots,重新编号后等价于 n/2n/2 人的子问题,再映射回去,得到 f(2m)=2f(m)1, f(2m+1)=2f(m)+1f(2m)=2f(m)-1,\ f(2m+1)=2f(m)+1。配合二进制:J(n)J(n) 就是把 nn 的二进制首位 1 移到末尾。

背后的数学

这是公元 1 世纪犹太历史学家约瑟夫斯记载的约瑟夫问题(Josephus Problem)。推广到任意步长 kk 用递推 J(n,k)=(J(n1,k)+k)modnJ(n,k)=(J(n-1,k)+k)\bmod n(从 J(1,k)=0J(1,k)=0 起)。它是最早把“圈”与“递推”结合的经典,也是模运算与循环Buffer的雏形。