连扔1000次硬币 出现过连续10次正面的概率(递归问题求解)

连扔1000次硬币 出现过连续10次正面的概率(递归问题求解)

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.50.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)+(1P(n10))/(211)

公式的含义是:
如果你扔n+1次,得到10或者以上正面的概率是扔n的概率(无论最后一次扔的是什么,都不会改变前n次拿到10次正面的概率),
加上从1到n-11次都没有连续10次的概率(这个概率即等于我们计算的 1 − P ( n − 11 ) 1-P(n-11) 1P(n11)),
乘以最后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层的递归,算了一夜都没算出来,估计缓存超了一直计算不出来,用数组内存后秒出结果。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是使用 Java 表示递归求解硬币兑换问题的代码: ```java public class CoinChange { private static final int INF = Integer.MAX_VALUE; public static int coinChange(int[] coins, int amount) { if (amount == 0) { return 0; } if (amount < 0) { return INF; } int ans = INF; for (int coin : coins) { int curAns = coinChange(coins, amount - coin); if (curAns == INF) { continue; } ans = Math.min(ans, curAns + 1); } return ans; } public static void main(String[] args) { int[] coins = {1, 2, 5}; int amount = 11; int ans = coinChange(coins, amount); System.out.println(ans); } } ``` 在这个代码中,我们定义了一个静态方法 `coinChange`,该方法接受两个参数:硬币面值数组 `coins` 和需要凑出的金额 `amount`,返回值是凑出指定金额所需的最少硬币数量。在方法中,我们首先处理几种边界情况:如果 `amount` 等于 0,表示已经凑出了指定的金额,不需要再进行任何操作,返回 0;如果 `amount` 小于 0,表示当前的硬币面值无法凑出指定的金额,返回一个非常大的数,表示无法凑出。 接下来,我们对于每一种硬币面值,都可以选择使用或者不使用,分别递归计算使用和不使用的情况下所需的硬币数量,取其中的较小值即可。在递归过程中,我们还需要注意特判无法凑出指定金额的情况,避免出现无限递归的情况。最后,我们在 `main` 方法中对代码进行测试,验证其正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值