NOIP模拟 赌博游戏 - 概率dp

题意:

最近西雅图的高中校园里流行这样一个游戏。
我们有一个骰子,这个骰子有M个面,分别写着1..M,并且是个公平的骰子,换句话说,一次投掷时每个面朝上的概率是相同的。
游戏的组织者使用这个骰子进行N次投掷,并且告诉玩家点数v出现了至少一次。那么玩家需要猜测N次投掷的点数之和。如果猜对了,就赢得了这个游戏。
小宇也喜欢玩这个游戏。在一次游戏中,她猜测了一个正整数sum,于是她想知道猜对的概率是多少。

分析:

设f[i][j][0/1]表示猜了i次,和为j,有(1)没有(0)猜中过v的概率。
转移很简单:
\(f[i][j][k == v] += f[i - 1][j - k][0]\)
\(f[i][j][1] += f[i - 1][j - k][1]\)
最后答案为: \(\frac{f[n][sum][1]}{\sum{f[n][j][1]}}\)

code

#include<bits/stdc++.h>
using namespace std;
int n, m, sum, v;
double tot, f[60][2600][2];

int main(){
    freopen("h.in", "r", stdin);
    scanf("%d%d%d%d", &n, &m, &v, &sum);
    f[0][0][0] = 1;
    for(int i = 1; i <= n; i++){
    	for(int j = 1; j <= n * m; j++){
    		for(int k = 1; k <= m; k++){
    			f[i][j][k == v] += 1.0*f[i - 1][j - k][0] / (1.0*m);
    			f[i][j][1] += 1.0*f[i - 1][j - k][1] / (1.0*m);
			}
		}
	}
	for(int i = 1; i <= n * m; i++) tot += f[n][i][1];
	printf("%.8f", f[n][sum][1] / tot);
	return 0; 
}
posted @ 2017-11-02 19:00  CzYoL  阅读(270)  评论(0编辑  收藏  举报