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}")
代码说明:
导入
math.comb(n, k)返回二项式系数 \(\binom{n}{k}\)。
solve
total_ways = comb(70, 20)计算从 70 个球中取 20 个的总方案数。ways_avoid_color = comb(60, 20)计算避开某一特定颜色(仅从其余 60 个球中取)的方案数。prob_absent为某颜色未出现的概率。prob_present = 1 - prob_absent为某颜色至少出现一次的概率。expected = 7 * prob_present由线性期望得到期望颜色数。
输出
- 以 9 位小数格式打印结果。