掷骰子

掷骰子

 

Problem Description

概率论的起源与赌博问题有关。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 的和。

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 const int N = 33;
 5 
 6 double dp[N][N][N];
 7 
 8 int main(){
 9     int n, m, c;  
10     while (cin >> n >> m >> c) {
11         memset(dp, 0.0, sizeof(dp));
12         dp[1][1][1] = 1.00;
13 /*“当前已投掷的次数”、“当前连续出现过最长的相同数字的次数”、“最后投掷的相同的数字的次数” */
14         for (int i = 1; i <= m; i++) {
15             for (int j = 1; j <= i; j++) {
16                 for (int k = 1; k <= j; k++) {
17                     double cur = dp[i][j][k];
18                     if (cur > 0){
19                         if (k + 1 > j){
20                            
21                             dp[i + 1][k + 1][k + 1] += cur * (1.0 / n); 
22                         } else {
23                             
24                             dp[i + 1][j][k + 1] += cur * (1.0 / n);
25                         }
26                       
27                         dp[i + 1][j][1] += cur * ((double)(n - 1) / n);
28                     }
29                 }
30             }
31         }
32 
33         double sums = 0.0;
34         for (int i = 1; i <= c; i++) {
35             sums += dp[m][c][i];
36         }
37         printf("%.3lf\n", sums);
38     }
39     return 0;
40 } 
View Code

 

posted @ 2019-07-18 14:55  龚政  阅读(663)  评论(0编辑  收藏  举报