跳转至

五张牌魔术:24 种排列怎么猜中 48 张底牌

题

一副去掉大小王的 52 张牌。1 号囚犯随机拿到 5 张,必须藏起 1 张,把剩下 4 张按从左到右的顺序摆在桌上;2 号只看这 4 张,就要报出藏起来的那张。两人进房间前可以约定一套策略。猜中释放,猜错处决。

用 24 种排列去对应 48 张可能的底牌,看起来最多只有 50% 的胜率。能保证 100% 猜中吗?

一句话

能。 24 种排列对 48 张底牌看似差一半,但 1 号还能决定藏哪张牌;同花色先定底牌花色,13 点圆环把 12 个点数折成 6 个步数,剩下 3 张的 6 种顺序把步数传过去1。

关键技巧

24 不是全部信号。 固定 4 张明牌时,它们的排列只有 \(4! = 24\) 种;底牌有 48 种可能,只看顺序确实最多覆盖一半。但藏哪张牌由 1 号自己选,5 张里藏 1 张、剩下 4 张再排,理论上有 \(5 \times 24 = 120\) 种动作。2 号看到的也不只是顺序——哪 4 张被留下、第一张是什么,都在传信。

动作多不等于能解码。下面三层把 48 种可能一路压到 1 种,每一层都要求两人提前约定同一套规则。

  • 抽屉原理定花色:5 张牌塞进 4 种花色,必有两张同花。1 号把其中一张放最左边,另一张藏起来;2 号看第一张的花色,就知道底牌的花色。未知从 48 种缩到同花色的 12 个点数。
  • 13 点圆环把 12 折成 6:同花色 A 到 K 围成 13 格圆环,K 的下一格接回 A。任意两张不同的同花牌,两个方向走的步数相加等于 13;13 是奇数,必有一个方向不超过 6 步。1 号把起点那张放第一位,终点那张藏起来,于是底牌一定在第一位顺时针 1–6 步内。
  • 3 张牌的全序把 6 折成 1:两人提前约定全序:先比点数,点数相同再按 ♠ > ♥ > ♣ > ♦ 比花色。剩下 3 张分出小、中、大,6 种排列固定对应 1–6。

13 点圆环:任意两张牌两个方向的步数相加等于 13

13 点圆环,K 的下一格接回 A

解

  1. 1 号看 5 张,找一对同花牌;选一张当起点,使另一张在顺时针 1–6 步内。起点放第一位,终点藏起来。
  2. 剩下 3 张按全序排成小、中、大;要传的步数 \(d\) 查下表,按对应排列摆放。
  3. 2 号看第一位:花色就是底牌花色,点数就是起点。后三张的顺序查表得到 \(d\),从起点顺时针数 \(d\) 步,报出底牌。
\(d\) 排列 例子(小 = 3♠,中 = 7♣,大 = K♦)
1 小中大 3♠ 7♣ K♦
2 小大中 3♠ K♦ 7♣
3 中小大 7♣ 3♠ K♦
4 中大小 7♣ K♦ 3♠
5 大小中 K♦ 3♠ 7♣
6 大中小 K♦ 7♣ 3♠

完整算例。 假设抽到 ♥10、♥2、♠3、♣7、♦K2。

  1. 两张红桃,从 ♥10 顺时针走到 ♥2:J、Q、K、A、2,共 5 步,没超过 6。于是把 ♥10 放第一位,藏 ♥2。
  2. 剩下 ♠3 < ♣7 < ♦K,即小、中、大;要传 5,查表用「大小中」,摆成 ♦K、♠3、♣7。
  3. 2 号看到第一位是 ♥10,知道底牌是红桃、起点 10;后三张是大小中,读出 5;从 10 顺时针数 5 步,报出 ♥2。

算例:第一位 ♥10,后三张 K、3、7 是大小中,底牌 ♥2

第一位定花色和起点,后三张的顺序定步数

延伸

  • 为什么 13 必须是奇数:圆环长 12 时两个方向可能都是 6 步,起点和终点分不清;13 保证总有一侧不超过 6 步、另一侧至少 7 步。
  • 5 张里有 3 张同花:任取其中两张按圆环定起点和终点,剩下 3 张照常编码;第三张同花牌留在明牌里也不影响解码。
  • 后三张同点数不同花色:按约定的花色序 ♠ > ♥ > ♣ > ♦ 分大小;全序保证 3 张牌一定能分出严格的小、中、大。
  • 24 对 48 的计数错在哪:24 是固定 4 张明牌时的排列数;1 号还能选藏哪张,理论动作 \(5 \times 24 = 120\) 种,2 号看到的是「哪 4 张 + 怎么排」。但动作多不等于能解码,上面的构造才是保证。
  • 来源与校正:整理自抖音「小偏导」的 6 分 37 秒视频3;口播把算例说成「7 点红桃 10」,圆环步数也转写错了,本文按画面校正为 ♥10、5 步。完整材料包在本地,不随站发布。
数值验证

枚举全部 \(\binom{52}{5} = 2{,}598{,}960\) 手牌,按上面的策略编码再解码,逐一核对是否能还原藏牌:

from itertools import combinations, permutations

PERMS = list(permutations(range(3)))

def card(r, s): return r * 4 + s
def rank(c): return c // 4
def suit(c): return c % 4
def key(c): return (rank(c), 4 - suit(c))   # 同点数按 ♠ > ♥ > ♣ > ♦

def encode(hand):
    by_suit = {}
    for c in hand:
        by_suit.setdefault(suit(c), []).append(c)
    a, b = next(v for v in by_suit.values() if len(v) >= 2)[:2]
    d = (rank(b) - rank(a)) % 13
    if d > 6:
        a, b, d = b, a, 13 - d
    rest = sorted((c for c in hand if c not in (a, b)), key=key)
    return [a] + [rest[i] for i in PERMS[d - 1]], b

def decode(seq):
    start, rest = seq[0], seq[1:]
    order = {c: i for i, c in enumerate(sorted(rest, key=key))}
    d = PERMS.index(tuple(order[c] for c in rest)) + 1
    return card((rank(start) + d) % 13, suit(start))

count = 0
for hand in combinations(range(52), 5):
    seq, hidden = encode(hand)
    assert decode(seq) == hidden
    count += 1
print(count)  # 2598960

  1. 转写 P01@00:00:00-00:02:34;关键帧 KF-P01-04。 ↩

  2. 转写 P01@00:04:47-00:05:59;关键帧 KF-P01-10、KF-P01-11。 ↩

  3. 抖音原视频,2026-10-19 读。 ↩