所有牌都被抽出的概率

机器算法验证 可能性 优惠券收集问题
2022-03-27 22:05:40

比方说,我有一副牌,我将从中随机抽取张牌,观察它们并将它们放回牌组中。我想知道; 抽之后有什么变化,我已经看到了甲板上的所有牌。mnk

它实际上是这里描述的问题的一个变体,但是在这种情况下,每次抽奖的项目数只有一个。

模拟

我做了一个模拟,其中甲板大小为 10,每次抽牌的牌数为 4,结果绘制在下面(这里是 python 代码)。 在此处输入图像描述

个人尝试

我只是为了计算单张牌不在单次平局中的概率:

P=(11m)(11m1)(11m2)(11m3)=i=1n(11mi+1)

2个回答

我认为解决方案会是这样的:

是在已经看到次抽牌中至少一次看到P(m,n,k,x,y)xky

那么P(m,n,k,x,0)=i=0xP(m,n,k1,xi,0)P(m,n,1,i,xi)

我认为和号下的可能性都是唯一的,所以我们可以将它们相加。

您的解决方案是剩下的就是定义并且我们应该能够递归地解决问题。P(m,n,k,m,0)P(m,n,1,i,xi)

编辑:Python中的完整解决方案,实现上述方法:

import numpy as np
from scipy.special import comb
import matplotlib.pyplot as plt
m = 10
n = 4
def P(k, x, y):
    if k == 1:
        return (comb(m-y, x) * comb(y, n-x))/comb(m, n)
    else:
        prob = 0
        for i in range(x):
            prob += P(k-1, x-i, y) * P(1, i, y+x-i)
        return prob

def P_MC(k, x, y):
    sims = 10000
    good = 0
    for s in range(sims):
        ar = np.arange(m)
        seen = set(np.arange(y))
        for draw in range(k):
            np.random.shuffle(ar)
            for el in ar[:n]:
                seen.add(el)
        if len(seen) == (x+y):
            good += 1
    return good/sims

ests = []
acts = []
for k in range(1,16):
    ests.append(P_MC(k, m, 0))
    acts.append(P(k, m, 0))

plt.plot(range(1,16), ests)
plt.plot(range(1,16), acts)
plt.grid()
plt.legend(['Simulated', 'Actual'], loc='lower right')

这是优惠券收集器问题的一个简单变体,它使用经典的占用分布。是已绘制的不同卡片的数量,根据经典占用分布 分布张不同的牌,并且随机抽牌时,每张牌至少抽一次的概率为:Kmnm

P(All cards drawn)=P(K=m)=m!S(n,m)mn,

其中函数表示第二类斯特林数这可以以显式形式写成:S

P(K=m)=i=0m(1)i(mi)(1im)n.