关于约瑟夫环问题递推公式的证明

2,176 阅读2分钟

问题描述与证明

  • 约瑟夫环问题:n个人围成一圈,第一个人从1开始报数,报m的将被淘汰,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。
  • 递推公式:f(n,m)=[f(n-1,m)+m]%n,其中f(i,j)表示当问题规模为i,报数长度为j时最后胜利者的编号。
  • 证明:使用数学归纳法进行证明。
  1. 当n=1时,f(1,m)=0,因为编号从0开始且只有一个人,胜利者编号显然为0。 当n=2时,序列为0,1,若m为奇数,则胜利者编号为1;若m为偶数,则胜利者编号为0,易有f(2,m)=m%2=(0+m)%2=[f(1,m)+m]%2,结论成立。
  2. 假设当n=i-1时结论成立,即对于序列0,1,2,...,i-2而言,最后的胜利者编号为f(i-1,m)。 当n=i时,序列为0,1,2,...,i-1。设第一轮的淘汰者编号为k(若m%i=0,则k=i-1,否则k=m%i-1),则序列可表示为0,1,2,...,k-1,k,k+1,...,i-1。第一轮淘汰k,余下的序列x'为k+1,...,i-1,0,1,...,k-1,问题规模变为i-1。 因为由归纳假设,当n=i-1时,对于序列x:0,1,2,...,f(i-1,m),...,i-2,胜利者编号为f(i-1,m)。由于x'=(x+k+1)%i,故f(i,m)=[f(i-1,m)+k+1]%i。当m%i=0时,k+1=i,[f(i-1,m)+k+1]%i=[f(i-1,m)+i]%i=f(i-1,m)%i+0=f(i-1,m)%i+m%i=[f(i-1,m)+m]%i;当m%i!=0时,k+1=m%i,[f(i-1,m)+k+1]%i=[f(i-1,m)+m%i]%i=[f(i-1,m)+m]%i。故当n=i时,结论成立。 综上,命题成立。
  • 感想:因为当n=i-1时,对于序列x:0,1,2,...,f(i-1,m),...,i-2,胜利者编号为f(i-1,m)。对于问题规模为i时,经过第一轮淘汰,得到序列x'。只要能够发现x与x'间的对应关系,由f(i-1,m)就能得到f(i,m)。

代码

class Solution {
public:
    int lastRemaining(int n, int m) {
        int res=0;
        for(int i=2;i<=n;i++)
            res=(res+m)%i;
        return res;
    }
};