07.2 組合數學#
本節目標#
- 理解階乘 \(n!\) 與二項式係數 \(\binom{n}{k}\) 的意義。
- 用 SymPy 的
factorial()、binomial()做排組計數,並驗證二項式定理。 - 驗證 \(\sum_{k=0}^{n} \binom{n}{k} = 2^n\) ,印出巴斯卡三角形。
- 實驗:計算各種賭局的勝率。
一、階乘與排列#
\(n! = 1 \times 2 \times \cdots \times n\) ,代表 \(n\) 個相異物全部排成一列的方法數(排列數 \(P_n = n!\) )。從 \(n\) 個中取出 \(k\) 個排列則是
from sympy import factorial, binomial, symbols, simplify, expand, Rational
n, k = symbols('n k', integer=True, nonnegative=True)
print(factorial(5)) # 120
print(factorial(0)) # 1(定義 0! = 1)
print(factorial(n)/factorial(n - 3)) # P(n,3) 的符號式
二、組合數 binomial#
\(\binom{n}{k} = \frac{n!}{k!(n-k)!}\) 代表從 \(n\) 個中「不計順序」取 \(k\) 個的方法數:
print(binomial(5, 2)) # 10
print(binomial(n, k)) # 符號形式,保留 n、k
# 驗證公式
print(simplify(binomial(n, k) - factorial(n)/(factorial(k)*factorial(n - k)))) # 0
對稱性質: \(\binom{n}{k} = \binom{n}{n-k}\) :
print(simplify(binomial(n, k) - binomial(n, n - k))) # 0
三、二項式定理驗證#
二項式定理:
用 expand 展開左式,再與右式逐項對照:
from sympy import summation
x, y = symbols('x y')
for N in [3, 5, 7]:
lhs = expand((x + y)**N)
rhs = summation(binomial(N, kk) * x**(N - kk) * y**kk, (kk, 0, N))
print(N, simplify(lhs - rhs) == 0)
# 全部印出 True
也觀察展開結果與係數的關係—— \(x^{n-k} y^k\) 項的係數正是 \(\binom{n}{k}\) :
print(expand((x + y)**4))
# x**4 + 4*x**3*y + 6*x**2*y**2 + 4*x*y**3 + y**4
# 係數 1, 4, 6, 4, 1 就是 binomial(4, k)
print([binomial(4, kk) for kk in range(5)]) # [1, 4, 6, 4, 1]
四、排組計數應用#
應用 1:passcode 密碼數。4 位數密碼,每位可為 0–9(可重複),共 \(10^4\) 種;若不可重複則是排列數:
# 可重複:每位 10 種選擇
print(10**4) # 10000
# 不可重複:P(10, 4)
print(factorial(10)/factorial(6)) # 5040
應用 2:撲克牌組合數。52 張牌發 5 張,不計順序:
total = binomial(52, 5)
print(total) # 2598960
應用 3:同花順的數目。4 種花色 × 10 種起點(A–10 連續五張):
straight_flush = 4 * 10
print(Rational(straight_flush, total).evalf()) # 約 0.0000154,極稀有
應用 4:委員會問題。10 人中選 4 人,其中指定 2 人必須同時選入或都不選:
# 2 人都選入:剩下從 8 人選 2;2 人都不選:從 8 人選 4
ways = binomial(8, 2) + binomial(8, 4)
print(ways) # 28 + 70 = 98
五、驗證 sum C(n,k) = 2^n#
組合意義:從 \(n\) 個物品中「任意選取」的總方法數(選 0 個、1 個、…、全部),就等於每個物品「選或不選」的 \(2^n\) 種組合:
from sympy import Eq, simplify
for N in [1, 5, 10, 20]:
s = summation(binomial(N, kk), (kk, 0, N))
print(N, s == 2**N)
# 符號層次的驗證(取幾個 n 檢查)
print(simplify(summation(binomial(7, kk), (kk, 0, 7)) - 2**7)) # 0
六、巴斯卡三角形#
巴斯卡三角形的第 \(n\) 列就是 \(\binom{n}{0}, \binom{n}{1}, \ldots, \binom{n}{n}\) ,且滿足
def pascal_triangle(rows):
for r in range(rows):
row = [binomial(r, kk) for kk in range(r + 1)]
print(' '.join(str(v) for v in row).center(rows * 4))
pascal_triangle(8)
# 1
# 1 1
# 1 2 1
# 1 3 3 1
# 1 4 6 4 1
# 1 5 10 10 5 1
# 1 6 15 20 15 6 1
# 1 7 21 35 35 21 7 1
驗證巴斯卡恆等式:
print(simplify(binomial(n + 1, k) - binomial(n, k - 1) - binomial(n, k))) # 0
每一列總和恰好是 \(2^n\) ,與上一節的恆等式互相呼應:
for r in range(8):
print(r, sum(binomial(r, kk) for kk in range(r + 1)))
七、動手實驗:算各種賭局勝率#
實驗 1:樂透 45 取 6,頭獎機率:
lotto = binomial(45, 6)
print(Rational(1, lotto)) # 1/8145060
print(Rational(1, lotto).evalf()) # 約 1.23e-7
實驗 2:骰子——擲兩顆,點數和為 7 的機率。樣本空間 \(6^2 = 36\) ,和為 7 有 6 種:
from sympy import Rational
print(Rational(6, 36)) # 1/6
實驗 3:擲 10 次硬幣,恰好 6 次正面的機率(二項分布):
p = binomial(10, 6) * Rational(1, 2)**10
print(p) # 105/512
print(p.evalf()) # 0.2051
# 至少 6 次正面的機率
p_at_least_6 = sum(binomial(10, kk) for kk in range(6, 11)) * Rational(1, 2)**10
print(p_at_least_6, float(p_at_least_6)) # 385/512 ≈ 0.7539
實驗 4:德州撲克拿到一對的機率(5 張中恰有一對):
# 選點數 13 種 × 從 4 張選 2 × 其餘 3 張點數互異且不同於對子
one_pair = 13 * binomial(4, 2) * binomial(12, 3) * 4**3
print(one_pair) # 1098240
print(Rational(one_pair, binomial(52, 5)).evalf()) # 約 0.4226
實驗 5:蒙特卡羅驗證——隨機發 5 張牌模擬一對的頻率:
import random
random.seed(42)
deck = list(range(52))
hits = 0
trials = 100000
for _ in range(trials):
hand = random.sample(deck, 5)
ranks = [h % 13 for h in hand]
if sorted(ranks) and max(ranks.count(r) for r in set(ranks)) == 2 \
and sorted(ranks.count(r) for r in set(ranks)) == [1, 1, 1, 2]:
hits += 1
print(hits / trials) # 應接近 0.4226
觀察重點: 1. 精確的分數(Rational)比浮點數更能表達機率的真值。 2. 組合數是所有「從有限集合選取」機率問題的基石。 3. 模擬結果會在精確值附近浮動, trials 越多越接近。
小結與練習#
本節我們學會了: - factorial(n) 與 binomial(n, k) 的用法與組合意義。 - 用 expand 驗證二項式定理 \((x+y)^n = \sum_{k=0}^{n} \binom{n}{k} x^{n-k} y^k\) 。 - \(\sum_{k=0}^{n} \binom{n}{k} = 2^n\) 及巴斯卡恆等式 \(\binom{n+1}{k} = \binom{n}{k-1} + \binom{n}{k}\) 。 - 用組合數計算密碼數、撲克牌型與各種賭局勝率。
練習: 1. 驗證 \(\sum_{k=0}^{n} (-1)^k \binom{n}{k} = 0\) (對 \(n \geq 1\) ),並用 \((1-1)^n\) 展開解釋。 2. 5 位英文字母密碼(不分大小寫、字母可重複),其中至少有一個字母重複出現的方法數有多少? 3. 計算橋牌(52 張發 13 張)的總組合數,並求拿到 13 張全是同一花色的機率。 4. 擲 20 次硬幣,正面次數最可能是幾次?用二項分布的組合數逐一算出機率找最大值。