约瑟夫环是一个数学的应用问题:已知 n 个人(以编号0,1,2,3…n-1分别表示)围坐在一张圆桌周围。从第一个人开始报数,数到 (m -1)的那个人出圈;他的下一个人又从0开始报数,数到 (m -1) 的那个人又出圈;依此规律重复下去,直到剩余最后一个胜利者。
为什么要从0开始编号,是为了方便后续代码实现,此处只有理论分析。
例如:有4个人围成一圈进行此游戏,每个人编号为 0-3 。若规定数到 2 的人出圈。则游戏过程如下。
(1)开始报数,第一个数到 2 的人为第三个人,出圈。
人数:1, 2, 【3】, 4
编号:0, 1, 【2】, 3
(2)从4号重新从0开始计数,则接下来数到2的人出圈。
人数:1, 【2】, 【3】, 4
编号:1, 【2】, X , 0
(3)再从4号重新从0开始计数,则接下来数到2的人出圈。
人数: 1, 【2】, 【3】,【 4】
编号①:1, X , X , 0
编号②:3, X , X ,【 2】
(4)所以胜利者为第一个人。
假设n个人(编号为0~(n-1),报到(m-1)的退出
编号为:0,1,2,3,...,【m-1】,m,m+1,....,n-1
第一个人(出列的)为(m%n-1),注意最后一个索引数为-1。
例如3个人,第三个人的编号是(m%n-1)= -1(与代码实现有关)
剩下的n—1个人重新编号。
那么编号就是从[(m%n-1)+1 ]=m%n开始
设为k=m%n
旧编号:k,k+1,k+2,... ,k - 2,k - 1→最终要求的解
新编号:0, 1 , 2, ...,n - 3,n - 2→已知解
假设有6个人
人数:1 2 3 4 5 6
编号:0 1 2 3 4 5
每次报到1,即m=2的人退出
那么原来的编号
2→0
3→1
4→2
5→3
0→4
设这里原来的解为y
现在的解为x
那么他们之间关系为y =(x+m)%n
依此类推,只要求出x,就能求出y
代码中递推公式
f[1]=0
f[i]=(f[i-1]+m)%i (i>1)