1、推导一波公式
看到这个问题可以从简单的情况出发,扔10次,11次……1000次
推导出概率
P
(
n
)
P(n)
P(n)和
P
(
n
+
1
)
P(n+1)
P(n+1)之间的关系(n为投掷次数)
1、n<10 这种情况肯定是不可能出现连续十次正面,因此
P
(
n
)
=
0
P(n)=0
P(n)=0
2、n=10: 只有一种情况,十次全为正
P
(
n
)
=
0.
5
10
=
1
/
1024
P(n)=0.5^{10}=1/1024
P(n)=0.510=1/1024
3、n=11: 有三种情况:1为反,2-11为正;1-10为正,11为反;1-11为正。
这种情况
P
(
11
)
P(11)
P(11)比
P
(
10
)
P(10)
P(10)多了哪些情况呢,当然是第一种情况啦,只有它是P(10)不能满足的。该情况的概率为
0.5
∗
0.
5
10
0.5*0.5^{10}
0.5∗0.510。
P
(
11
)
=
P
(
10
)
+
0.
5
11
P(11)= P(10)+0.5^{11}
P(11)=P(10)+0.511
4、得到公式
P
(
n
+
1
)
=
P
(
n
)
+
(
1
−
P
(
n
−
10
)
)
/
(
2
11
)
P(n+1) = P(n)+(1-P(n-10))/(2^{11})
P(n+1)=P(n)+(1−P(n−10))/(211)
公式的含义是:
如果你扔n+1次,得到10或者以上正面的概率是扔n的概率(无论最后一次扔的是什么,都不会改变前n次拿到10次正面的概率),
加上从1到n-11次都没有连续10次的概率(这个概率即等于我们计算的
1
−
P
(
n
−
11
)
1-P(n-11)
1−P(n−11)),
乘以最后11扔是1个背面加上10个正面的概率(
1
/
2
11
1/2^{11}
1/211)
2、编写代码计算
/**
* @description:连扔1000次硬币 出现过连续10次正面的概率
* @author: 陶芃宇
* @date: 2020-12-08 19:37
*/
public class coins {
public static double[] doubles = new double[1000];
public static void main(String[] args){
for (int i = 0; i < 1000; i++) {
doubles[i]=formula(i);
}
System.out.println(doubles[999]);
}
public static double formula(int n) {
if(n<10){
return 0;
} else if(n==10) {
return Math.pow(0.5, 10);
}
return doubles[n-1]+(1-doubles[n-11])/2048;
}
}
3、注意事项
递归问题我们可以用数组将每一步的结果存储起来,一开始写这个代码的时候直接写出来一个1000层的递归,算了一夜都没算出来,估计缓存超了一直计算不出来,用数组内存后秒出结果。