掷骰子

这篇博客探讨了概率论中的掷骰子问题,特别是在连续掷骰子中出现特定连续相同面的概率计算。通过分析每次投掷骰子可能出现的情况,提出了利用'目前最长相同字符串'和'最后相同字符串的长度'的概念来求解概率的方法。文章提供了输入输出样例,并解释了如何根据骰子的面数和投掷次数来计算连续x个相同面的概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                                掷骰子 

        概率论的起源与赌博问题有关。16世纪,意大利的学者吉罗拉莫•卡尔达诺(Girolamo Cardano,1501——1576)开始研究掷骰子等赌博中的一些简单问题。17世纪中叶,当时的法国宫廷贵族里盛行着掷骰子游戏,游戏规则是玩家连续掷 4 次骰子,如果其中没有 6 点出现,玩家赢,如果出现一次 6 点,则庄家(相当于现在的赌场)赢。按照这一游戏规则,从长期来看,庄家扮演赢家的角色,而玩家大部分时间是输家,因为庄家总是要靠此为生的,因此当时人们也就接受了这种现象。那么现在让我们来计算一个概率问题。
一个骰子有n(4≤n≤8)个面,随机投掷m(1≤m≤32)次,请计算出现连续x个相同面的概率(C)。(结果请四舍五入到小数点后第3位。)

Input

每行3个用空格分开的整数,分别表示n,m,x。

Output

每行一个数,表示概率C。

Sample Input

4 5 3

Sample Output

0.129

 

 

分析:需要求抛 m次后,连续x次相同面的骰子的概率,我们可以分为一次一次的抛,那么第 i 次 和 第 i - 1 次的状况只有两种。

第一:  两次的点数相同, 那就是 1/n

第二:两次的点数不同,那就是 (n-1)/n

假设连续抛了10次,假设点数为字符,有可能为:

AAABB CCC DD

AAABC CDAAA

AAABC DERTY

AAABC DDDDD

也就是说,存在一个“目前最长相同字符串”(now_len)。和 “最后相同字符串的长度(last_len)”.

result = max(now_len, last_len)

同时可以知道,当last_len > now_len 时, now_len = last_len.

根据最后一次抛的情况,我们可以更新 last_len, 然后更新last_len 去更新 now_len,最后得到答案。

当最后一次和前一次不同时, last_len = 1,  概率为 (n-1)/n

当最后一次和前一次相同时, last_len = last_len + 1; 概率为 1 / n

        当last_len > now_len 时, now_len = last_len.

 

请计算出现连续x个相同面的概率(C), 就是算,当now_len = X 的时候, last_len 从 1 到now_len 的和。

#include<bits/stdc++.h>

using namespace std;
const int N = 33;

double dp[N][N][N];

int main(){
    int n, m, c;  
    while (cin >> n >> m >> c) {
        memset(dp, 0.0, sizeof(dp));
        dp[1][1][1] = 1.00;
        /*
            i,相当于抛的次数,j 相当于now_len, k 相当于 last_len
        */
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= i; j++) {
                for (int k = 1; k <= j; k++) {
                    double cur = dp[i][j][k];
                    if (cur > 0){
                         /*
                            最后一次抛的结果和上一次一样, last_len + 1
                         */  
                        if (k + 1 > j){
                           /*
                                last_len > now_len,抛的次数i+1, now_len = last_len

                           */
                            dp[i + 1][k + 1][k + 1] += cur * (1.0 / n); 
                        } else {
                            
                            dp[i + 1][j][k + 1] += cur * (1.0 / n);
                        }
                        /*
                            最后一次抛的结果和上一次不一样,那么 抛的次数 i + 1, now_len不变,last_len = 1
                        */
                        dp[i + 1][j][1] += cur * ((double)(n - 1) / n);
                    }
                }
            }
        }

        double sums = 0.0;
        for (int i = 1; i <= c; i++) {
            sums += dp[m][c][i];
        }
        printf("%.3lf\n", sums);
    }
    return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值