2024春晚魔术原理—约瑟夫环问题

首先祝大家新年快乐,龙年大吉!相信大家都对昨晚春晚的魔术记忆深刻(即使没看过,也一定看到了尼格买提穿帮的新闻)。接下来就来模拟一下昨晚刘谦的魔术,并扒扒其原理。

1.魔术模拟

Step 1:假设有四张牌,编号为 1、2、3、4

Step 2:四张卡牌对折撕开,并重叠

Step 3:根据自己名字的字数下放牌;例如名字字数为 2,则序列如下所示

Notice:这是无效操作,并不会对最终效果产生影响。

Step 4:拿起前三张牌,插进剩下牌的中间

Notice:这一步操作,要求插进中间的卡牌数必须为 3,因为两张相同牌的中间隔了 3 张卡牌;经过这样的操作后,能够保证头和尾是相同卡牌;其次插进的位置只要不是头和尾,不会对结果造成影响

Step 5:隐藏第一张卡牌,此时隐藏的卡牌是 2

Step 6:南方朋友拿起前一张卡牌;北方朋友拿起前两张卡牌;自己不知道是南方和北方的朋友拿起前三张卡牌。将这些卡牌插入剩下卡牌的中间。示例拿起一张,结果如下所示

Notice:这一步操作是无效操作;无论拿几张牌,以及插入在哪个位置,只要保证卡牌 2 在最后即可

Step 7:男生拿起前一张卡牌;女生拿起前两张卡牌;将这些卡牌扔掉。两种情况如下所示

Notice:这一步的操作是保证卡牌总数为 6 或 5

Step 8:大喊 "见证奇迹的时刻",每喊一个字将一张卡牌下方,总共下放 7 次

Notice:这一步是关键操作,其主要目的是为了将卡牌 2 放置到最后一步的约瑟夫环问题的答案位置

Step 9:第一张卡牌将其下放,第二张卡牌将其丢掉;该步骤操作四次

Notice:这一步操作的本质是约瑟夫环问题;其将这一序列排成一个环,为每个卡牌编号(从0开始,如 Step 8 所示),从 0 开始报数,报到 2 的卡牌移除;然后从移除卡牌的下一个卡牌开始重新报数,最后留下的卡牌就是与隐藏卡牌配对的卡牌。

约瑟夫环问题的公式为:
f ( n , m ) = { 0 n=1 f ( n − 1 , m ) + m % n n>1 f(n,m)=\begin{cases} 0& \text{n=1}\\ f(n-1,m)+m\%n & \text{n>1} \end{cases} f(n,m)={0f(n−1,m)+m%nn=1n>1

其中 n 代表卡牌数,m = 2。

根据公式可知: f ( 6 , 2 ) = 4 f(6,2)=4 f(6,2)=4; f ( 5 , 2 ) = 2 f(5,2)=2 f(5,2)=2

其结果正好是 Step 8 中卡牌 2 的位置。

根据以上的模拟过程是不是已经清楚这个魔术的原理了呢~接下来讨论一下约瑟夫环问题的推导过程。

2.约瑟夫环问题数学推导过程

1.问题描述

假设有 n n n 个人围成一个圈,根据某一顺序为每一个人设置一个编号 0 、 1 、 2 、 ... 、 n − 1 0、1、2、\dots、n-1 0、1、2、...、n−1。从编号 0 开始报数,报到 m m m 的人出圈;然后从出圈人的下一个人重新开始报数。重复该操作,直到只剩下一个人,这个人就是赢家。

2.示例说明

假设有 6 个人,报到 2 的人出圈。其执行过程如下所示:

3.数学推导

定义:

  • 在序列 0 、 1 、 2 、 ... 、 n − 1 0、1、2、\dots、n-1 0、1、2、...、n−1 执行约瑟夫环操作,最后剩下的编号为 f ( n , m ) f(n,m) f(n,m)
  • 执行完第一次约瑟夫环操作后,出圈的编号为 k k k,则下一次操作的序列为 k + 1 、 k + 2 、 ... 、 n − 1 、 0 、 1 、 ... 、 k − 1 k+1、k+2、\dots、n-1、0、1、\dots、k-1 k+1、k+2、...、n−1、0、1、...、k−1,在该序列上的约瑟夫环操作,最后剩下的编号为 g ( n − 1 , m ) g(n-1,m) g(n−1,m)
  • 从以上的定义可知, f ( n , m ) = g ( n − 1 , m ) f(n,m)=g(n-1,m) f(n,m)=g(n−1,m)

重新映射:

将执行完第一次约瑟夫环操作后得到的新序列进行重新编号,从 0 开始,则其映射关系如下表所示:

原编号 新编号
k + 1 k+1 k+1 0 0 0
k + 2 k+2 k+2 1 1 1
... \dots ... ... \dots ...
n − 1 n-1 n−1 n − k − 2 n-k-2 n−k−2
0 0 0 n − k − 1 n-k-1 n−k−1
1 1 1 n − k n-k n−k
... \dots ... ... \dots ...
k − 1 k-1 k−1 n − 2 n-2 n−2

根据以上的映射关系,可以总结得到以下的公式:
h ( x ) = { x − k − 1 k+1 <= x <= n-1 x + n − k − 1 0 <= x <=k-1 h(x)=\begin{cases} x-k-1& \text{k+1 <= x <= n-1 }\\ x+n-k-1 & \text{0 <= x <=k-1} \end{cases} h(x)={x−k−1x+n−k−1k+1 <= x <= n-1 0 <= x <=k-1

∵ k + 1 ≤ x ≤ n − 1 → 1 ≤ x − k ≤ n − k − 1 → 0 ≤ x − k − 1 ≤ n − k − 2 \because k+1 \le x \le n-1 \ \ \rightarrow \ \ 1 \le x-k \le n-k-1 \ \ \rightarrow \ \ 0 \le x-k-1\le n-k-2 ∵k+1≤x≤n−1 → 1≤x−k≤n−k−1 → 0≤x−k−1≤n−k−2

n ≤ x + n − k − 1 ≤ n + n − k − 2 \ \ \ n \le x+n-k-1 \le n+n-k-2 n≤x+n−k−1≤n+n−k−2

∴ n % n = 0 ≤ ( x + n − k − 1 ) % n ≤ ( 2 ∗ n − k − 2 ) % n = n − k − 2 \therefore n\%n=0 \le (x+n-k-1)\%n \le (2*n-k-2)\%n=n-k-2 ∴n%n=0≤(x+n−k−1)%n≤(2∗n−k−2)%n=n−k−2

∴ 式子 ( x + n − k − 1 ) % n ,当 k + 1 ≤ x ≤ n − 1 时, 0 ≤ h ( x ) ≤ n − k − 2 \therefore 式子 (x+n-k-1)\%n,当\ k+1 \le x \le n-1\ 时,0 \le h(x) \le n-k-2 ∴式子(x+n−k−1)%n,当 k+1≤x≤n−1 时,0≤h(x)≤n−k−2

∵ 0 ≤ x ≤ k − 1 → n ≤ x + n ≤ n + k − 1 → n − k ≤ x + n − k ≤ n − 1 \because 0 \le x \le k-1 \ \ \rightarrow \ \ n \le x+n \le n+k-1 \ \ \rightarrow \ \ n-k \le x+n-k \le n-1 ∵0≤x≤k−1 → n≤x+n≤n+k−1 → n−k≤x+n−k≤n−1

n − k − 1 ≤ x + n − k − 1 ≤ n − 2 \ \ \ n-k-1 \le x+n-k-1 \le n-2 n−k−1≤x+n−k−1≤n−2

∴ ( n − k − 1 ) % n = n − k − 1 ≤ ( x + n − k − 1 ) % n ≤ ( n − 2 ) % n = n − 2 \therefore (n-k-1)\%n=n-k-1 \le (x+n-k-1)\%n \le (n-2)\%n=n-2 ∴(n−k−1)%n=n−k−1≤(x+n−k−1)%n≤(n−2)%n=n−2

∴ 式子 ( x + n − k − 1 ) % n ,当 0 ≤ x ≤ k − 1 时, n − k − 1 ≤ h ( x ) ≤ n − 2 \therefore 式子 (x+n-k-1)\%n,当\ 0 \le x \le k-1\ 时,n-k-1 \le h(x) \le n-2 ∴式子(x+n−k−1)%n,当 0≤x≤k−1 时,n−k−1≤h(x)≤n−2

∴ 可将公式统一为 h ( x ) = ( x + n − k − 1 ) % n \therefore 可将公式统一为\ \ h(x)=(x+n-k-1)\%n ∴可将公式统一为 h(x)=(x+n−k−1)%n

为了消除求余号 % \% % ,可以引入正整数 T T T,以达到求余的效果;公式如下所示:

h ( x ) = ( x + n − k − 1 ) % n = ( x + n − k − 1 ) + ( T − 1 ) n = x − k − 1 + T n h(x)=(x+n-k-1)\%n=(x+n-k-1)+(T-1)n=x-k-1+Tn h(x)=(x+n−k−1)%n=(x+n−k−1)+(T−1)n=x−k−1+Tn

推导:

∵ f ( n − 1 , m ) \because f(n-1,m) ∵f(n−1,m) 是在重新映射后的序列上的约瑟夫环操作结果

∴ f ( n − 1 , m ) = h ( g ( n − 1 , m ) ) \therefore f(n-1,m)=h(g(n-1,m)) ∴f(n−1,m)=h(g(n−1,m))

∴ g ( n − 1 , m ) = h − 1 ( f ( n − 1 , m ) ) \therefore g(n-1,m)=h^{-1}(f(n-1,m)) ∴g(n−1,m)=h−1(f(n−1,m))

∵ x = h ( x ) + k + 1 − T n \because x=h(x)+k+1-Tn ∵x=h(x)+k+1−Tn

∴ h − 1 ( x ) = x + k + 1 − T n = ( x + k + 1 ) % n \therefore h^{-1}(x)=x+k+1-Tn=(x+k+1)\%n ∴h−1(x)=x+k+1−Tn=(x+k+1)%n

∴ g ( n − 1 , m ) = h − 1 ( f ( n − 1 , m ) ) = f ( n − 1 , m ) + k + 1 % n \therefore g(n-1,m)=h^{-1}(f(n-1,m))=f(n-1,m)+k+1\%n ∴g(n−1,m)=h−1(f(n−1,m))=f(n−1,m)+k+1%n

∵ k \because k ∵k 是第一次约瑟夫环操作的结果,可知 k = ( m − 1 ) % n k=(m-1)\%n k=(m−1)%n

∴ g ( n − 1 , m ) = f ( n − 1 , m ) + ( m − 1 ) % n + 1 % n = f ( n − 1 , m ) + m % n \therefore g(n-1,m)=f(n-1,m)+(m-1)\\%n+1\%n=f(n-1,m)+m\%n ∴g(n−1,m)=f(n−1,m)+(m−1)%n+1%n=f(n−1,m)+m%n

∵ f ( n , m ) = g ( n − 1 , m ) \because f(n,m)=g(n-1,m) ∵f(n,m)=g(n−1,m)

∴ f ( n , m ) = f ( n − 1 , m ) + m % n \therefore f(n,m)=f(n-1,m)+m\%n ∴f(n,m)=f(n−1,m)+m%n

代码:

java 复制代码
public int findWinner(int n,int m){
    if(n==1) return 0;
    int winner = findWinner(n-1,m);
    return (winner+m)%n;
}

3.参考文献

相关推荐
通信小呆呆15 小时前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
benben04415 小时前
强化学习之DQN算法族(基于gymnasium开发)
算法
何以解忧,唯有..16 小时前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
想吃火锅100517 小时前
【leetcode】88.合并两个有序数组js
算法
生成论实验室18 小时前
机器人:一个自主运动的系统
人工智能·算法·语言模型·机器人·自动驾驶·agi·安全架构
Qres82118 小时前
算法复键——树状数组
数据结构·算法
H1785350909618 小时前
SolidWorks第四部分_直接实体建模特征9_替换面原理
线性代数·算法·机器学习·3d建模·solidworks
不会就选b18 小时前
算法日常・每日刷题--<二分查找>3
算法
绿算技术19 小时前
Mooncake 与绿算ForinnBase GroundPool如何联手打破推理僵局?
科技·算法·架构