随机游走002 | 面试智力题——求投掷硬币连续出现若干次及以上正面的概率
0. 引言
现在越来越多的企业面试会考察智力题,以判断面试者的逻辑思维能力。前段时间朋友在面试某基金公司时碰到了一个颇有意思的概率题,由于笔者最近在学习随机过程,看到这道题倍感亲切,便写来分享,提供一种思路。
1. 问题
投掷1万次硬币(概率均等),求出现连续100次或以上硬币正面朝上的概率。
2. 分析
我们以"出现连续100次正面朝上"表示"出现连续100次或以上正面朝上",区别于"出现恰好连续100次正面朝上",那么对投掷次数进行分析:
-
当投掷次数小于100时,出现连续100次正面朝上的概率必然为\(0\);
-
当投掷次数为100时,所求概率为"100次投掷全为正面朝上"的概率\(P(100)=2^{-100}\);
-
当投掷次数为101时,所求概率为"前100次投掷已出现100次正面朝上"的概率+"第101次投掷时首次出现连续100次正面朝上"的概率:\(P(101)=2^{-100}+2^{-101}\);
-
当投掷102次时,所求概率为"前101次投掷已出现100次正面朝上"的概率+"第102次投掷时首次出现连续100次正面朝上"的概率\(P(102)=2^{-100}+2^{-101}+2^{-101}\);
-
当投掷\(k\)次,\(101\leq k\leq200\)时,所求概率\(P(k)=2^{-100}+(k-100)\cdot2^{-101}\)。但此通项公式无法继续下去,因为当投掷201次时,第201次投掷首次出现连续100次正面朝上的除了需要101次投掷结果为反面朝上,102至201次投掷全为正面朝上,还需要前100次投掷中不出现连续100次正面朝上。因此,投掷201次时,所求概率为
\[P(201)=\left(2^{-100}+100\cdot 2^{-101}\right)+(1-2^{-100})\cdot2^{-101} \] -
记投掷\(k\)次硬币,出现连续100次正面朝上的概率为\(P(k),\)有递推关系:
\[\begin{align} P(k)&=0,\forall 0\leq k \leq99,\quad P(100)=2^{-100},\\ P(k)&=P(k-1)+(1-P(k-101))\cdot 2^{-101},\forall k\geq 101. \end{align} \]
至此,本问题已经基本解决,但本文希望利用随机过程的工具来看待该问题。首先,根据延迟更新过程相关结论(参考Ross, Stochastic Processes, 2nd Edition: 126),可以计算首次出现连续100次正面朝上结果的期望投掷次数:
因此,可以想象,在1万次投掷中出现连续100次硬币正面朝上的概率十分微小,趋近于0。此外,我们可以通过构建离散时间马尔科夫链(Discrete-time Markov Chain)来更清晰地描述该问题。
3. 建模
投掷\(n\)次硬币(概率均等),求出现连续\(m\)次或以上硬币正面朝上的概率。
构建离散时间马尔科夫链如下,状态空间共\(m+1\)个状态,其中状态"\(i\)",\(i=0,1,\dots,m-1\)表示当前时刻下已连续出现\(i\)次正面朝上;状态"\(m\)"表示截至当前时刻,出现过连续\(m\)次正面朝上。由于出现过连续\(m\)次在正面朝上后,这个事实不会随着时间的推移而改变,因此后续将一直保持该状态,即状态"\(m\)"为吸收态(absorbing state),而其他状态均为瞬态(transient state),即在无限长时间内只能返回有限次的状态。
容易构造出1步转移概率矩阵\(\mathbb{P}=(P_{ij})_{\{(m+1)\times(m+1)\}}\),其中
根据 C-K 公式(Chapman-Kolmogorov Equation),有
而我们所求的概率即\(P_{0\,m}^{n}\),表示从状态"\(0\)"开始,经过\(n\)步最终达到状态"\(m\)"的概率,只需对转移概率矩阵求\(n\)次幂即可。
考虑到上述步骤需要求\((m+1)\times(m+1)\)阶矩阵的\(n\)次幂,当\(m\)和\(n\)较大时,计算复杂度较高。好在由于转移概率矩阵\(\mathbb{P}\)有大量元素为\(0\),因此通过转移概率矩阵的幂运算也能推导出第2节中的递推公式。首先,
进一步地,
因此,得到\(P_{0\,m}^k\) 关于转移步数 \(k\) 的递推公式:
4. 程序
myfunc1 <- function(m, n){
timestart <- Sys.time()
p <- vector()
p[1:(m-1)] <- 0
p[m] <- 0.5^m
p[m+1] <- p[m] + 0.5^(m+1)
for (i in (m+2):n){
p[i] <- p[i-1] + (1 - p[i-m-1])*0.5^(m+1)
}
timeend <- Sys.time()
runningtime <- timeend-timestart
show(runningtime)
return(p[length(p)])
}
myfunc1(10, 1000)
myfunc1(10, 10000)
myfunc1(100, 10000)
myfunc2 <- function(m, n){
timestart <- Sys.time()
P <- matrix(0, nrow = m+1, ncol = m+1, dimnames = list(0:m, 0:m))
P[1:m, 1] <- 0.5
for(i in 1:m){
P[i, i+1] <- 0.5
}
P[m+1, m+1] <- 1
PP <- matrix(diag(1, m+1, m+1), nrow = m+1, ncol = m+1, dimnames = list(0:m, 0:m))
for(i in 1:n){
PP <- PP %*% P
}
timeend <- Sys.time()
runningtime <- timeend-timestart
print(runningtime)
return(PP[1, m+1])
}
myfunc2(10, 1000)
myfunc2(10, 10000)
myfunc2(100, 10000)
> myfunc1(10, 1000)
Time difference of 0.0009989738 secs
[1] 0.3854498
> myfunc1(10, 10000)
Time difference of 0.00549984 secs
[1] 0.9925839
> myfunc1(100, 10000)
Time difference of 0.006980896 secs
[1] 3.90565e-27
> myfunc2(10, 1000)
Time difference of 0.001994133 secs
[1] 0.3854498
> myfunc2(10, 10000)
Time difference of 0.02394104 secs
[1] 0.9925839
> myfunc2(100, 10000)
Time difference of 6.898201 secs
[1] 3.90565e-27
计算得:投掷1000次硬币,出现连续10次或以上硬币正面朝上的概率为0.3854498;投掷10000次硬币,出现连续10次或以上硬币正面朝上的概率为0.9925839(吸收态极限概率为1);投掷10000次硬币,出现连续100次或以上硬币正面朝上的概率为3.90565e-27(趋近0)。此外通过递推公式求解的算法省略了其他状态的\(n\)步转移概率的计算,大大节约了计算时间。
5. 资料
- 知乎相关问题讨论页面
- Sheldon M. Ross, Stochastic Processes, 2nd Edition, 1995.

浙公网安备 33010602011771号