人生一手牌
过年的时候,和爸爸、小朋友,爷孙三代一起打争上游,三个人一副牌,爷爷赢得多。
我不太记得具体的输赢局数,只记得抓到了两次炸弹。抓到炸弹,在感觉上是一件很奇妙的事情,每一个花色里的同一张牌,正好在手上集齐。
结束以后让小朋友尝试计算抓到炸弹的概率,也问了豆包和DeepSeek,都不太满意,自己来求解一下。
比如,在4张A里面,玩家抓到4张A可能出现的情况只有一种:\(C_{4}^{4}\)
除了4张A以外,玩家可能抓到4张2、4张3,共有13种可能性:\(13 * C_{4}^{4}\)
因为每人抓18张,总数为54张,因此需要在剩下的50张牌里,分别14张给玩家,组合的总数是: \(C_{50}^{14}\)
总的可能性是,在54张牌里随机分配18张: \(C_{54}^{18}\)
因此,粗略的算法是:
\[P_{\text{至少一个}} \approx \frac {C_{4}^{4} \times 13 C_{50}^{14}} {C_{54}^{18}}\]计算的数字很大,放到 desmos 上面,友好的结果秒出: 12.57%
之所以是粗略算法,因为上面的算法存在重复统计的情况:
比如,按照先前的思路,分不同的情况进行加总:
情况1: 给玩家分配4张A,然后在剩下的50张里面,给玩家分配14张
情况2: 给玩家分配4张2,然后在剩下的50张里面,给玩家分配14张
…
情况13:给玩家分配4张K,然后在剩下的50张里面,给玩家分配14张
所有抓到炸弹的可能组合数是上面的13种情况之和,在情况1剩余分配的14张里面,也有可能包含了4张2,也就是玩家抓到了两副炸弹,在情况2里面,也可能还有4张A。因此上述的算法存在重复统计。个人感觉上重复统计的情况应该挺少的,因为你可以回忆一下,在一个牌局里面,甩出两副及以上的炸弹的情况常不常见。
本着严谨的态度,需要用上容斥原理:
\[组合情况 = \sum_{k=0}^{max}{(-1)^k} \binom{12}{k} \binom{54-4-4k}{18-4-4k}\]通过交替加减来排除多个炸弹被玩家抓到从而被重复统计的情况,即:
\[P_(炸弹概率) = 13\cdot\frac{\left(\operatorname{nCr}\left(50,14\right)-12\cdot\operatorname{nCr}\left(46,10\right)+66\cdot\operatorname{nCr}\left(42,6\right)-220\cdot\operatorname{nCr}\left(38,2\right)\right)}{\operatorname{nCr}\left(54,18\right)}\]最后的答案是 11.93%
大于10%的概率,有点出乎意料。写个python代码,运行了1亿次,模拟一下结果:
import random
from collections import Counter
T = 100_000_000 # Target loops
counts = [0, 0, 0, 0, 0, 0]
valid_trials = 0 # 确保运行满目标次数, 严谨一些
random.seed()
while valid_trials < T:
# 抽18张牌
hand = random.sample(range(54), 18)
# 统计频数
num = Counter(0 if a < 2 else (a - 2) // 4 + 1 for a in hand)
# 0的位置留给大小王,出现3张以上大小王或者5张以上其它花色牌应该排除
if num[0] > 2 or any(count > 4 for count in num.values()):
continue
count_fours = sum(1 for key, count in num.items() if 1 <= key <= 13 and count == 4)
counts[count_fours] += 1
valid_trials += 1
scenarios = [
"没有炸弹: {}",
"1 副炸弹: {}",
"2 副炸弹: {}",
"3 副炸弹: {}",
"4 副炸弹: {}",
"5 副炸弹: {}"
]
for i, scenario in enumerate(scenarios):
print(scenario.format(counts[i]))
炸弹副数 | 出现次数 |
---|---|
没有炸弹 | 87743954 |
1 副炸弹 | 11930164 |
2 副炸弹 | 324313 |
3 副炸弹 | 1569 |
4 副炸弹 | 0 |
5 副炸弹 | 0 |
打一亿次牌,每天打100局,一年365天从无间断,天天打,需要2700多年。在这么长的牌局里,没有抓到炸弹的概率是87%,抓到1副的概率是11.93%。
抓到4副,理论上有可能,18张牌里有16张是组成炸弹的牌,实际上没有发生。抓到3副的概率是十万分之一。十万分之一的概念是,按照每天打100局,坚持20年,总共是73万局,用程序模拟运行了一下,抓到3副炸弹的概率是6次,基本上不用期望它会发生在你身上。
抓到1副炸弹,概率是11.93%的体感含义是什么?
让我们简化一下,假设抓到炸弹的概率是10%,即1/10,常识理解是打10次牌,抓到一次。但是可能会碰到的错误理解是,因为概率是10%,那么只要打10次,就肯定会抓到一次,因为 \(10 * 10 = 100%\)。 这种想法是错误的,但是在生活中却很有代表性。如果按照这种简单地把概率线性加起来的做法,那么打20次,岂不是概率就成为200%了?
中奖的概率是10%,那么没有中奖的概率是90%,至少抽中一次的概率就是用1减去连续每次都不中的概率。
把连续抽 N 次得到的中奖概率,用程序跑一下:
import numpy as np
# 抽奖次数: 1 到 70次
n = np.arange(1, 71)
# 至少中奖 1 次的概率
p = 1 - (1 - 0.10) ** n
输出结果如下:
抽奖次数 (n) | 至少中奖 1 次的概率 (%) |
---|---|
1 | 10.00 |
2 | 19.00 |
3 | 27.10 |
4 | 34.39 |
5 | 40.95 |
6 | 46.86 |
7 | 52.17 |
8 | 56.95 |
9 | 61.26 |
10 | 65.13 |
11 | 68.62 |
12 | 71.76 |
13 | 74.58 |
14 | 77.12 |
15 | 79.41 |
16 | 81.47 |
17 | 83.32 |
18 | 84.99 |
19 | 86.49 |
20 | 87.84 |
21 | 89.06 |
22 | 90.15 |
… | … |
30 | 95.76 |
40 | 98.52 |
… | … |
50 | 99.48 |
… | … |
60 | 99.82 |
… | … |
70 | 99.93 |
前面所谓连续抽10次,其实概率只有65%,并不高。如果设70%为高概率,那么需要抽12次。 如果坚持到22次,那么概率是90%,而22次一直到70次,都是在90以上徘徊,直至99.9,非常接近于1。
人生的牌局啊,有人比较早就抓了比较好的一手牌,有的人却好像一直都牌风不顺。
上面的数字告诉我们:
如果想要赢一把,不论之前的牌面如何,最重要的是能够stay on the table,只要能够一直在桌面上,那么,多数人可以有的运气,也可以到你身上。 几乎是确定的事实。
小朋友喜欢玩牌。
我自己倒是很一般,之前团队流行玩德州,在团建的时候玩过,在前面几把我就all in了,结果我的游戏早早结束。
玩牌和德州,更像是信息的博弈,有的时候需要虚张声势,而我并不喜欢这一类型。我更偏向于下棋,没有时间限制的下棋,可以慢慢地下,慢慢地想。