约瑟夫环问题


约瑟夫环问题

$n$ 个人围成一圈,从第一个开始报数,数到第 $m$ 个的人会被杀掉,直到剩下一个人,求解最后存活的是哪一个人。

抽象描述

$0,1,2,…,n-1$ 这些数字围成一圈,从第 $0$ 个数字开始,每次删除第 $m$ 个数字,求最后剩下的那个数字。

解法

Definition 1: $f(n,m)$

$f(n,m)$:表示 $n$ 个数字围成一圈,从第 $0$ 个数字开始,每次删除第 $m$ 个数字,最后剩下的那个数字。

$0,1,2,…,n-1$ 这 $n$ 个数字中,被删除的是数字 $(m-1)%n$,令 $k=(m-1)%n$,则第一次删除后剩下的数字为 $0,1,2,…,k-1,k+1,…,n-1$,下一次删除是从 $k+1$ 开始数,于是我们可以把该序列改写为 $k+1,…,n-1,0,1,…,k-1$。

Definition 2: $g(n-1,m)$

$g(n-1,m)$:表示从 $k+1,…,n-1,0,1,…,k-1$ 这 $n-1$ 个数字中,从 $k+1$ 开始,每次删除第 $m$ 个数字,最后剩下的那个数字。

显然,$f(n,m)=g(n-1,m)$。(因为最后剩下的数字是同一个)

Definition 3: $h(x)$

$h(x)$:一个从 $f(n-1,m)$ 到 $g(n-1,m)$ 的映射。

下面求解这个 $h(x)$,观察如下映射规则:
$0\rightarrow k+1$

$1\rightarrow k+2$
$…$
$n-3\rightarrow k-2$
$n-2\rightarrow k-1$
可得:$h(x)=(x+k+1)%n$,因此有:

f(n,m)=g(n1,m)=h(f(n1,m))=(f(n1,m)+k+1)%n=(f(n1,m)+(m1)%n+1)%n=((f(n1,m)+1)%n+(m1)%n)%n=((f(n1,m)+1)+(m1))%n=(f(n1,m)+m)%n

其中$①:0\leq f(n-1,m)\leq n-2$,$1\leq f(n-1,m)+1\leq n-1$,因此 $(f(n-1,m)+1)%n= f(n-1,m)+1$

$②:distributive\ law:(a+b)%p=(a%p+b%p)%p$

最终我们有递推公式:

f(n,m)={0n=0(f(n1,m)+m)%nn>1

代码实现

递归

int josephus(int n, int m) {
    if (1 == n) {
        return 0;
    }
    return josephus(n - 1, m) % n;
}

动态规划

int josephus(int n, int m) {
    int dp = 0;
    for (int i = 2; i <= n; ++i) {
        dp = (dp + m) % i;
    }
    return dp;
}

文章作者: xitie2000
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xitie2000 !
评论
  目录