YouTuberのセイキンさんが
『大人が全力で新作ハッピーセット「スーパーマリオ」全種類集めてみた。』
という動画でハッピーセットを20個購入し、おもちゃ10種類をコンプリートしていました。
運がいいような気もしますが、実際にこの条件でおもちゃをコンプリートする確率はいくつでしょうか。
気になったので、数学とPythonを使ってこの確率を求めてみます。
以下の流れで進めます。
- 数学で一般の場合について考察(問1)
- Pythonで実際の確率を計算(問2)
問1
ハッピーセットを $m$ 個購入したとき、おもちゃ $n$ 種類をコンプリートする確率はいくつか?
解1
$m < n$ ならば求める確率は $0$ である。
$m \geq n$ とする。
以降の計算を簡単にするため、 $k = m - n \geq 0$ とおく。
ハッピーセットを $m = n + k$ 個購入し、おもちゃ $n$ 種類をコンプリートする確率 $p_{n k}$ を求める($n \geq 1,\, k \geq 0$)。
おもちゃの当たり方は、全部で $n^{n + k}$ 通りある。
この中で、おもちゃをコンプリートする場合の数を $a_{n k}$ とする。
a_{1 k} = 1,\, a_{n 0} = n!
である。また、おもちゃをコンプリートする場合は、最後の1個の購入でちょうどコンプリートする場合と、それ以前に既にコンプリートした場合に分けられるため
a_{n k} = n (a_{n - 1, k} + a_{n, k - 1})
\hspace{1em}
(n \geq 2,\, k \geq 1)
が成り立つ。この漸化式を解くと
a_{n 0} = n!,
\hspace{1em}
a_{n k} = n!
\sum_{1 \leq i_1 \leq \cdots \leq i_k \leq n} i_1 \cdots i_k
\hspace{1em}
(k \geq 1)
となる。ただし右辺の $\sum$ は、 $1 \leq i_1 \leq \cdots \leq i_k \leq n$ を満たすような自然数の組 $i_1, ..., i_k$ 全体について積 $i_1 \cdots i_k$ の和をとったものである。
よって求める確率 $p_{n k} = a_{n k} / n^{n + k}$ は
p_{n 0} = \frac{n!}{n^n},
\hspace{1em}
p_{n k}
=
\frac{n!}{n^{n + k}}
\sum_{1 \leq i_1 \leq \cdots \leq i_k \leq n} i_1 \cdots i_k
\hspace{1em}
(k \geq 1)
となる。
問2
ハッピーセットを $20$ 個購入したとき、おもちゃ $10$ 種類をコンプリートする確率はいくつか?
解2
解1をもとに、ハッピーセットを $20$ 個購入し、おもちゃ $10$ 種類をコンプリートする確率をPython 3で計算します。
ただし、漸化式を解いた結果は逆に扱いづらいので、残念ですが漸化式そのものを扱うことにしましょう。
import functools
import math
@functools.lru_cache()
def a(n: int, k: int) -> int:
if n == 1:
return 1
if k == 0:
return math.factorial(n)
return n * (a(n - 1, k) + a(n, k - 1))
def p(n: int, k: int) -> float:
return a(n, k) / (n ** (n + k))
if __name__ == '__main__':
print(p(n = 10, k = 10)) # n + k = 20, k = 10
結果は
0.21473732319740063
約 $21.5$ %でした。
セイキンさんはラッキーだったようですね。