NOIP模拟(11.02)T4 赌博游戏

来源:互联网 发布:.us域名查询 编辑:程序博客网 时间:2024/05/16 19:20

赌博游戏

题目背景:

11.02 NOIP模拟T4

分析:DP

 

讲道理这个题比T3简单的多啊······直接定义f[i][j]表示已经投掷了i次,目前的和是j的方案数,一次枚举转移的时候用1 ~ m都进行转移,第二次再DP一遍f[i][j],这一次的转移跳过v不进行枚举,然后两次的f[n][sum]相减,就是一定包含至少一次v并且sum满足答案的方案数,然后因为至少出现一次v的总方案数为mn - (m - 1)n,直接用之前两次的差值除以总方案数就可以了,注意要用double

Source:

/*created by scarlyw*/#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <string>#include <cstring>#include <cctype>#include <vector>#include <queue>#include <set>#include <ctime>const int MAXN = 50 + 10;double ans = 0;long double f[MAXN][MAXN * MAXN | 1];int n, m, v, sum;int main() {freopen("gamb.in", "r", stdin);freopen("gamb.out", "w", stdout);scanf("%d%d%d%d", &n, &m, &v, &sum);f[0][0] = 1;for (int i = 1; i <= n; ++i)for (int j = 1; j <= n * m; ++j)for (int k = 1; k <= j && k <= m; ++k)f[i][j] += f[i - 1][j - k];ans = f[n][sum];memset(f, 0, sizeof(f));f[0][0] = 1;for (int i = 1; i <= n; ++i)for (int j = 1; j <= n * m; ++j)for (int k = 1; k <= j && k <= m; ++k) {if (k == v) continue ;f[i][j] += f[i - 1][j - k];}ans -= f[n][sum];long double l = 1, r = 1;for (int i = 1; i <= n; ++i) l *= (long double)(m - 1), r *= (long double)m;ans /= (r - l);printf("%0.8f", (double)ans);return 0;}