493. 彩虹之下(Under the Rainbow)

一个瓮中放有 70 个彩色球,七种彩虹颜色每种各 10 个。

随机取出 20 个球,问其中不同颜色数量的期望值是多少?

答案保留九位小数(格式为 a.bcdefghij)。

分析:利用期望的线性性,将问题转化为每种颜色是否出现的指示变量之和。每种颜色未出现的概率可以直接用组合数表达。

一、数学背景

定义指示变量 \(I_i\)\(i=1,\dots,7\)):

$$I_i = \begin{cases} 1 & \text{颜色 }i\text{ 至少出现一次} \\ 0 & \text{颜色 }i\text{ 未出现} \end{cases}$$

不同颜色总数 \(X = \sum_{i=1}^{7} I_i\),由期望的线性性:

$$E[X] = \sum_{i=1}^{7} E[I_i] = 7 \cdot P(\text{某指定颜色至少出现一次})$$

从 70 个球中取 20 个的总方案数为 \(\binom{70}{20}\)。完全不取某颜色的 10 个球的方案数为从其余 60 个球中取 20 个,即 \(\binom{60}{20}\)。因此:

$$P(\text{某颜色未出现}) = \frac{\binom{60}{20}}{\binom{70}{20}}$$
$$E[X] = 7 \cdot \left(1 - \frac{\binom{60}{20}}{\binom{70}{20}}\right)$$

二、算法设计

直接使用 Python 的 math.comb 计算组合数,代入公式求期望值。时间复杂度 \(O(1)\)

三、复杂度分析

计算两个组合数 \(\binom{70}{20}\)\(\binom{60}{20}\),均为大整数运算,但 Python 内置的 math.comb 在 70 级别上是瞬时的。总耗时在毫秒级。

四、代码实现与说明

"""
Project Euler Problem 493: Under the Rainbow

70 colored balls (7 colors, 10 each) in an urn.
Pick 20 balls randomly without replacement.
Find the expected number of distinct colors among the 20 picked balls.
"""

from math import comb


def solve() -> float:
    """Compute expected number of distinct colors using linearity of expectation."""
    total_ways = comb(70, 20)
    ways_avoid_color = comb(60, 20)

    prob_absent = ways_avoid_color / total_ways
    prob_present = 1 - prob_absent

    expected = 7 * prob_present
    return expected


if __name__ == "__main__":
    result = solve()
    print(f"{result:.9f}")

代码说明:

导入

solve

输出