如何修改生日问题代码,计算3人及以上、4人及以上同生日的概率?
生日问题扩展:计算多人同生日的概率
原生日问题探讨的是:房间中至少需要多少人,才能使至少两人拥有相同生日的概率超过50%。现在需要修改代码,计算至少3人及以上、4人及以上(以此类推)群体同生日的概率,直接修改原代码中的变量c为3是行不通的——原代码逻辑仅适用于两人同生日的场景,多人同生日的概率计算逻辑完全不同。
问题分析
原代码核心是计算「所有人生日都不同」的概率,再用1减去该值得到至少两人同生日的概率。但要计算至少m人同生日的概率,需要排除两类情况:
- 所有人生日都互不相同
- 仅存在两两同生日的组合,没有任何m人及以上同生日的情况
我们可以用模拟法(直观易扩展)或容斥原理的理论计算法实现需求。
方法1:模拟法(推荐,易扩展)
通过多次随机模拟人群生日统计,直接统计出现至少m人同生日的次数,用频率近似概率,代码修改和扩展都很简单:
import numpy as np def calculate_m_same_birthday_probability(m, k, n_days=365, trials=10000): """ 计算k个人中至少有m人生日相同的概率 :param m: 同生日人数阈值(如3、4) :param k: 房间内的人数 :param n_days: 一年的天数,默认365 :param trials: 模拟次数,次数越多结果越准确 """ count = 0 for _ in range(trials): # 生成k个随机生日(1到365之间的整数) birthdays = np.random.randint(1, n_days+1, size=k) # 统计每个生日的出现次数 unique, counts = np.unique(birthdays, return_counts=True) # 检查是否有生日出现次数≥m if np.any(counts >= m): count += 1 # 计算概率 prob = count / trials return prob # 示例:计算50人中至少3人生日相同的概率 m = 3 k = 50 prob = calculate_m_same_birthday_probability(m, k) print(f"{k}人中至少{m}人生日相同的概率:{prob:.4f}")
代码说明
- 调整
m的值即可计算4人及以上同生日的概率,比如将m=4代入函数 trials越大,模拟结果越接近真实概率,默认10000次足够日常使用- 可修改
n_days适配特殊场景(如闰年366天)
方法2:理论计算法(基于容斥原理)
如果需要精确理论值,可使用容斥原理计算,但逻辑相对复杂,以下是计算至少3人同生日概率的示例:
from math import comb, factorial def theoretical_m_same_birthday(m, k, n_days=365): if m == 2: # 原生日问题的计算逻辑 return 1 - factorial(n_days) / (factorial(n_days - k) * (n_days ** k)) elif m == 3: # 至少3人同生日概率 = 1 - 全不同概率 - 仅存在两两同生日的概率总和 prob_all_distinct = factorial(n_days) / (factorial(n_days - k) * (n_days ** k)) # 计算仅存在t对两人同生日的概率总和 prob_exactly_pairs = 0 max_t = k // 2 for t in range(1, max_t + 1): # 选t个不同的生日作为重复项 choose_birthdays = comb(n_days, t) # 从k人中选2*t个人分成t对 choose_people = factorial(k) / ( (2**t) * factorial(t) * factorial(k - 2*t) ) # 剩余k-2*t人分配到剩余n_days-t个不同生日 remaining = factorial(n_days - t) / factorial(n_days - t - (k - 2*t)) # 该情况的概率 prob_t = (choose_birthdays * choose_people * remaining) / (n_days ** k) prob_exactly_pairs += prob_t return 1 - prob_all_distinct - prob_exactly_pairs # 示例:计算50人中至少3人生日相同的理论概率 m = 3 k = 50 prob = theoretical_m_same_birthday(m, k) print(f"{k}人中至少{m}人生日相同的理论概率:{prob:.4f}")
代码说明
- 当
m>3时,容斥原理需要考虑更多复杂场景(如同时存在3人同生日和两两同生日、多组3人同生日等),代码复杂度会显著提升,此时模拟法更实用 - 理论计算法适合需要高精度结果的场景
原代码修改c无效的原因
原代码中的c=2对应两两组合数k*(k-1)/2,用于泊松近似计算两人同生日的概率,这个逻辑仅适用于两人同生日的场景,和多人同生日的概率计算没有直接关联,因此修改c无法得到正确结果。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

