对不重复随机数的数学分析

一、引子——双色球 我们知道,双色球每注投注号码由 6 个红色球号码和 1 个蓝色球号码组成。红色球号码从 1—33 中选择;蓝色球号码从 1—16 中选择。现在要求写出一个程序,模拟双色球的抽奖过程。 我们很容易想到使用某种方法生成一定范围内的随机数。蓝色球很好解决,但对于红色球,需要的是随机生成 6 个号码不同的数,可一定范围内的随机数总可能出现相同的情况,这样要如何解决? 也就是说:对于 $1, 2, ..., m$ 这 m 个数字,随机抽取其中 $n(n \lt m)$ 个数。要采取怎样的算法? 二、两种思路 其一 : 暴力方法 的确,随机数总有可能出现相同的情况,但是我们知道,同一个数多次出现的概率很小,以至于我们可以将其忽略。因此,我们只需要不断地取范围内的随机数,遇到重复的舍弃,直到取得的数字数目达到 n 即可。 void rand1(int m, int n, int rands[]) { char* hasSelect = calloc(m+1, sizeof(char)); for (int i = 0; i < n; ) { int r = randomInt(1, m); if (!hasSelect[r]) { rands[i++] = r; hasSelect[r] = 1; } } free(hasSelect); } 但这种算法是有缺陷的。问题在于,概率达到多小才算作可以忽略? 考虑 $m=100, n=99$ 的情况。首先,取得第一个球,一定只需要选取 1 次;但是,我们再计算一下取得最后一个球的选取次数。为了取得第 99 个数,选中的概率为 $p_{99} = \frac{1}{50}$。我们设离散型随机变量 $X$ 表示为了取得第 99 个数所需的选取次数,则 $P\{X = k\} = (1-p)^{k-1}p$ 服从几何分布。因此 $E(X) = \frac{1}{p} = 50$。从期望上看,需要整整 50 次才能取到第 99 个数!!这中间的差距说明了,在 m 一定时,随着 n 的增大,随机的效率明显降低。...

十一月 13, 2022 · 3 分钟 · 569 字 · Wokron