跳转至

掷到 6、全程偶数的期望次数

题

一颗公平骰子反复掷,出现 6 就停。已知从头到尾掷出的每个点数都是偶数,求掷骰次数的条件期望。

一句话

答案是 \(3/2\),不是 3——"全程偶数"不是把骰子换成只有 \(\{2,4,6\}\) 的三面骰,而是只保留那些没来得及出奇数就碰到 6 的序列。越长的序列越可能混进奇数,被筛掉;留下来的都偏短。

关键技巧

把条件改写成停止规则。 定义新停时 \(M\) = 首次掷出 \(\{1, 3, 5, 6\}\) 中任一点的时刻。于是:

  • 事件 \(A\)(全程偶数)\(\iff\) \(M\) 那一次掷出的是 6——在出现 6 之前没有奇数,等价于 \(\{1,3,5,6\}\) 里第一个出现的是 6。
  • 在 \(A\) 上,\(N = M\)。

\(M\) 之前的每一掷都是 2 或 4,\(M\) 那一掷在 \(\{1,3,5,6\}\) 上均匀且与 \(M\) 独立——"掷了多少个 2/4 才停"不影响"停在哪个点"。所以

\[ E[N \mid A] = E[M \mid X_M = 6] = E[M] = \frac{1}{4/6} = \frac32 \]

顺带 \(P(A) = P(X_M = 6) = \frac14\)。

解

直接算也就两行。\(N = n\) 且全程偶数,意味着前 \(n-1\) 次是 2 或 4、第 \(n\) 次是 6:

\[ P(N = n,\ A) = \left(\tfrac13\right)^{n-1} \cdot \tfrac16, \qquad P(A) = \sum_{n\ge1} \left(\tfrac13\right)^{n-1} \tfrac16 = \tfrac14 \]
\[ P(N = n \mid A) = \tfrac23 \left(\tfrac13\right)^{n-1}, \qquad E[N \mid A] = \frac{1}{2/3} = \frac32 \]

条件分布是成功率 \(\frac23\) 的几何分布——正好就是"每掷一次有 \(\frac46\) 的机会停下"的 \(M\)。

延伸

  • 错在哪:答 3 的人默认了"已知全偶 = 每一掷都从 \(\{2,4,6\}\) 均匀抽"。这把条件当成了对过程的改造,实际上条件是对样本路径的筛选。前者停止概率每步 \(\frac13\),后者每步 \(\frac23\)——奇数点并没有消失,它们以"让这条路径作废"的方式参与了停止。
  • 一般化:掷到出现目标集 \(S\) 为止,已知全程避开禁区 \(B\)(\(S \cap B = \varnothing\)),则 \(N \mid A\) 服从几何分布,成功率 \(\frac{|S| + |B|}{6}\),期望 \(\frac{6}{|S|+|B|}\)。本题 \(|S| = 1\)、\(|B| = 3\),给 \(\frac64\)。
  • 同一个坑的其他面孔:两个孩子问题 与 Monty Hall 都是"信息怎么来的"决定条件概率——条件不是凭空加在世界上的限制,而是一次观察。
  • 检验直觉的办法:把条件化写成模拟里的 if ok: 过滤,而不是改写掷骰函数——代码结构本身就会告诉你哪个模型是对的。
数值验证

几何级数精确解、错误模型、拒绝采样与等价停止规则两路蒙特卡洛:

from fractions import Fraction as F
import random

# 精确:P(N = n 且全程偶数) = (1/3)^(n-1) * (1/6),几何级数求和
r, c = F(1, 3), F(1, 6)
PA = c / (1 - r)                               # sum_n c r^(n-1)
EN = c / (1 - r) ** 2 / PA                     # sum_n n c r^(n-1) / P(A)
print(PA, EN)                                  # 1/4 3/2
print([c * r ** (n - 1) / PA for n in (1, 2, 3)])
# [Fraction(2, 3), Fraction(2, 9), Fraction(2, 27)]  -> 几何分布 p = 2/3

# 错误模型:只在 {2,4,6} 里掷直到 6
print(F(1) / F(1, 3))                          # 3

# 等价停止规则:掷到 {1,3,5,6} 之一就停,停时恰为 6 才算数
random.seed(6)
T, kept, tot, tot_eq, cnt_eq = 10 ** 6, 0, 0, 0, 0
for _ in range(T):
    n, ok = 0, True
    while True:
        x = random.randint(1, 6); n += 1
        if x % 2: ok = False
        if x == 6: break
    if ok: kept += 1; tot += n
    n = 0
    while True:
        x = random.randint(1, 6); n += 1
        if x in (1, 3, 5, 6): break
    tot_eq += n; cnt_eq += 1
print(kept / T, tot / kept, tot_eq / cnt_eq)  # 0.250317 1.5007370654010714 1.499458