魔术《守岁共此时》揭秘

魔术介绍

魔术《守岁共此时》是 2024 2024 2024 年春节联欢晚会上刘谦表演的魔术。刘谦共表演了两个魔术,其中的第二个魔术为观众共同参与的魔术。

第二个魔术的操作内容如下。

  1. 任取 4 4 4 张牌,打乱顺序。
  2. 4 4 4 张牌撕开,变成 8 8 8 个小张,按同一个方向放置。放置之后得到 8 8 8 个小张组成的牌叠,上面 4 4 4 张为 4 4 4 张牌的上半部分,下面 4 4 4 张为 4 4 4 张牌的下半部分,且上面 4 4 4 张与下面 4 4 4 张的相对顺序相同。
  3. 根据每个人的姓名字数 x x x,每次将牌叠最上面的牌放到最下面,重复 x x x 次该操作。
  4. 拿起牌叠最上面的 3 3 3 张牌,插进牌叠的中间任意位置。
  5. 拿起牌叠最上面的 1 1 1 张牌,藏在其他地方。
  6. 拿起牌叠最上面的 1 1 1 3 3 3 张牌,插进牌叠的中间任意位置。具体数量为:南方人拿 1 1 1 张,北方人拿 2 2 2 张,不确定者拿 3 3 3 张。
  7. 拿起牌叠最上面的 1 1 1 2 2 2 张牌,丢弃。具体数量为:男生拿 1 1 1 张,女生拿 2 2 2 张。
  8. 每次将牌叠最上面的牌放到最下面,重复 7 7 7 次该操作。
  9. 每次将牌叠最上面的牌放到最下面,然后把牌叠最上面的牌丢弃,直到剩下 1 1 1 张牌。由于第 7 7 7 步男生丢弃的牌比女生少 1 1 1 张,因此第 9 9 9 步男生需要多执行 1 1 1 次操作。
  10. 剩余的 1 1 1 张牌与第 5 5 5 步藏起的牌匹配。

魔术分析

4 4 4 张牌分别记为 A \text{A} A B \text{B} B C \text{C} C D \text{D} D,撕开后 A \text{A} A B \text{B} B C \text{C} C D \text{D} D 各有 2 2 2 张。经过前 2 2 2 步操作之后,牌叠顺序是 ABCDABCD \text{ABCDABCD} ABCDABCD,满足同一张牌的 2 2 2 个半张在牌叠中的距离为 4 4 4。本文中,牌叠顺序都是从上到下的顺序。

3 3 3 步操作后的牌叠顺序取决于 x x x 除以 4 4 4 的余数,具体如下。

  • x x x 除以 4 4 4 0 0 0 时,第 3 3 3 步操作后的牌叠顺序是 ABCDABCD \text{ABCDABCD} ABCDABCD

  • x x x 除以 4 4 4 1 1 1 时,第 3 3 3 步操作后的牌叠顺序是 BCDABCDA \text{BCDABCDA} BCDABCDA

  • x x x 除以 4 4 4 2 2 2 时,第 3 3 3 步操作后的牌叠顺序是 CDABCDAB \text{CDABCDAB} CDABCDAB

  • x x x 除以 4 4 4 3 3 3 时,第 3 3 3 步操作后的牌叠顺序是 DABCDABC \text{DABCDABC} DABCDABC

虽然可能有 4 4 4 种不同的牌叠顺序,但是都满足同一张牌的 2 2 2 个半张在牌叠中的距离为 4 4 4。以下考虑第 3 3 3 步操作后的牌叠顺序为 ABCDABCD \text{ABCDABCD} ABCDABCD 的情况,对于其他牌叠顺序的情况也适用。

4 4 4 步操作之后,牌叠最上面的牌与最下面的牌都是 D \text{D} D,中间的牌的顺序是任意的。

5 5 5 步操作将牌叠最上面的牌藏在其他地方,藏起的牌是 D \text{D} D。第 5 5 5 步操作之后,牌叠还有 7 7 7 张牌。

6 6 6 步操作会改变牌叠的上面 6 6 6 张牌的顺序,牌叠最下面的牌仍是 D \text{D} D。第 6 6 6 步操作之后,将牌叠顺序记为 EFGHIJD \text{EFGHIJD} EFGHIJD

7 7 7 步操作将牌叠最上面的 1 1 1 2 2 2 张牌丢弃,男生丢弃 1 1 1 张牌,女生丢弃 2 2 2 张牌。第 7 7 7 步操作之后,男生的牌叠还有 6 6 6 张牌,牌叠顺序是 FGHIJD \text{FGHIJD} FGHIJD,女生的牌叠还有 5 5 5 张牌,牌叠顺序是 GHIJD \text{GHIJD} GHIJD

8 8 8 步操作将牌叠最上面的 7 7 7 张牌放到最下面。第 8 8 8 步操作之后,男生的牌叠顺序是 GHIJDF \text{GHIJDF} GHIJDF,女生的牌叠顺序是 IJDGH \text{IJDGH} IJDGH

9 9 9 步操作时,男生需要丢弃 5 5 5 张牌,女生需要丢弃 4 4 4 张牌。男生和女生的每次操作之后的牌叠顺序变化如下。

  • 男生: GHIJDF → HIJDFG → IJDFG → JDFGI → DFGI → FGID → GID → IDG → DG → GD → D \text{GHIJDF} \rightarrow \text{HIJDFG} \rightarrow \text{IJDFG} \rightarrow \text{JDFGI} \rightarrow \text{DFGI} \rightarrow \text{FGID} \rightarrow \text{GID} \rightarrow \text{IDG} \rightarrow \text{DG} \rightarrow \text{GD} \rightarrow \text{D} GHIJDFHIJDFGIJDFGJDFGIDFGIFGIDGIDIDGDGGDD

  • 女生: IJDGH → JDGHI → DGHI → GHID → HID → IDH → DH → HD → D \text{IJDGH} \rightarrow \text{JDGHI} \rightarrow \text{DGHI} \rightarrow \text{GHID} \rightarrow \text{HID} \rightarrow \text{IDH} \rightarrow \text{DH} \rightarrow \text{HD} \rightarrow \text{D} IJDGHJDGHIDGHIGHIDHIDIDHDHHDD

9 9 9 步操作之后,剩余的 1 1 1 张牌是 D \text{D} D,与第 5 5 5 步藏起的牌匹配。

整个魔术过程中,关键的操作有第 4 4 4 步操作、第 5 5 5 步操作、第 7 7 7 步操作、第 8 8 8 步操作和第 9 9 9 步操作,关键操作决定了待匹配的牌 D \text{D} D 的位置与剩余牌的数量。

推广到约瑟夫问题

约瑟夫问题与求解

魔术的第 9 9 9 步操作可以推广到一般形式:有 n n n 张牌围成一个圆圈,按顺时针顺序的编号依次是 1 1 1 n n n,从编号 1 1 1 的牌开始,每次向顺时针方向数 k k k 张牌并将第 k k k 张牌丢弃,直到最后只剩余 1 1 1 张牌,需要计算剩余的牌的编号。该问题为经典的约瑟夫问题。

约瑟夫问题的解法有多种。最简单的解法是模拟,时间复杂度是 O ( n k ) O(nk) O(nk),空间复杂度是 O ( n ) O(n) O(n)。更优的解法是数学解法,时间复杂度是 O ( n ) O(n) O(n),数学解法可以使用递归或迭代实现,递归实现的空间复杂度是 O ( n ) O(n) O(n),迭代实现的空间复杂度是 O ( 1 ) O(1) O(1)

f ( n , k ) f(n, k) f(n,k) 表示约瑟夫问题的解。可以使用递归的方式计算 f ( n , k ) f(n, k) f(n,k)

递归的基准情形是 n = 1 n = 1 n=1,此时圆圈中只有 1 1 1 张编号是 1 1 1 的牌,因此 f ( 1 , k ) = 1 f(1, k) = 1 f(1,k)=1

n > 1 n > 1 n>1 时,记 prevRemain = f ( n − 1 , k ) \textit{prevRemain} = f(n - 1, k) prevRemain=f(n1,k),则 prevRemain \textit{prevRemain} prevRemain n − 1 n - 1 n1 张牌中剩余的牌。如果 n n n 张牌的起始牌的编号是 1 1 1,则首张被丢弃的牌的编号是 k k k,剩余 n − 1 n - 1 n1 张牌时的起始牌的编号是 1 + k 1 + k 1+k。因此, n n n 张牌时剩余的牌的编号是 prevRemain \textit{prevRemain} prevRemain 按顺时针方向数 k k k 位。

由于牌的编号范围是 [ 1 , n ] [1, n] [1,n],因此 f ( n , k ) = ( prevRemain + k − 1 )   m o d   n + 1 f(n, k) = (\textit{prevRemain} + k - 1) \bmod n + 1 f(n,k)=(prevRemain+k1)modn+1

迭代实现根据递归实现得到。用 winner \textit{winner} winner 表示剩余的牌的编号,初始时 winner = 1 \textit{winner} = 1 winner=1。对于 2 ≤ i ≤ n 2 \le i \le n 2in,从小到大遍历每个 i i i,并将 winner \textit{winner} winner 的值更新为 ( winner + k − 1 )   m o d   i + 1 (\textit{winner} + k - 1) \bmod i + 1 (winner+k1)modi+1。遍历结束时, winner \textit{winner} winner 即为 n n n 张牌时剩余的牌的编号。

代码实现

下面的代码为数学解法的递归实现。

class Solution {
    public int findRemainCard(int n, int k) {
        if (n == 1) {
            return 1;
        }
        int prevRemain = findRemainCard(n - 1, k);
        return (prevRemain + k - 1) % n + 1;
    }
}

下面的代码为数学解法的迭代实现。

class Solution {
    public int findRemainCard(int n, int k) {
        int remain = 1;
        for (int i = 2; i <= n; i++) {
            remain = (remain + k - 1) % i + 1;
        }
        return remain;
    }
}

你可能感兴趣的:(其他,刘谦,魔术,约瑟夫问题)