zoukankan      html  css  js  c++  java
  • [ZOJ3329] One Person Game

    传送门:>出错啦<

    题意:有三个骰子,每个骰子分别有$k_1,k_2,k_3$面,若三个骰子分别骰到a, b, c则计数器归0,否则计数器加上三个骰子得到的数之和。求计数器达到n及以上所需要骰的次数的期望。

    解题思路:

      继续期望DP。

      $f[i]$表示从i分到达n分所需要骰的次数的期望,因此$f[n] = 0$ 答案为$f[0]$

      设骰一次(三个骰子之和)骰到$k$分的概率为$p[k]$,$p[0]$的概率即为骰到$a,b,c$的概率,只有$frac{1}{k_1*k_2*k_3}$。另外的累积一下可能性,也除以总可能性就可以了。

      由i分转移到i+j分,分别加上相应的概率。并且还要特殊处理计数器清0的情况:清零的可能性乘以0分的期望。于是我们很容易得到方程:$$f[i] = sumlimits_{j=1 j != a+b+c}^{k_1+k_2+k_3}(p[j] * f[i+j]) + f[0] * p[0] + 1$$

      但是注意,$f[0]$是我们要求的答案,怎么反而用来转移了?所以这个方程很不可行……

      但是在这个递推式中,除了$f[0]$之外都是已知的,所以我们可以把它看做一个关于$f[0]$一次函数:$$f[i] = k * f[0] + b$$

      并且我们发现系数只与$i$有关,所以 $ f[i] = A[i] * f[0] + B[i] $

      因此可以替换$f[i+j]$:$$f[i] = sumlimits_{j=1 j != a+b+c}^{k_1+k_2+k_3}(p[j] * (A[i+j] * f[0] + B[i+j])) + f[0] * p[0] + 1$$

      因此$$A[i] = A[i+j] * p[j] + p[0]$$$$B[i] = B[i+j] * p[j] + 1$$

      特殊的,当$i == 0$时:$$f[0] = A[0] * f[0] + B[0]$$

      也就是$$f[0] = frac{B[0]}{1 - A[0]}$$

      这就是答案

    Code

      不要先做完再memset了

    /*By QiXingzhi*/
    #include <cstdio>
    #include <queue>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int N = 1010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
        return x * w;
    }
    int n,a,b,c,k1,k2,k3,T;
    double p[N],A[N],B[N];
    inline void Solve(){
        p[0] = (double)1.0 / (double)(k1*k2*k3);
        for(int k = 3; k <= k1 + k2 + k3; ++k) p[k] = 0.0;
    //    printf("p[0] = %.5lf
    ",p[0]);
        for(int i = 1; i <= k1; ++i){
            for(int j = 1; j <= k2; ++j){
                for(int k = 1; k <= k3; ++k){
                    if(i==a && j==b && k==c) continue;
                    p[i+j+k] += 1.0;
    //                printf("P[%d] = %d
    ",i+j+k,P[i+j+k]);
                }
            }
        }
        for(int k = 3; k <= k1+k2+k3; ++k){
            p[k] = (double)(p[k]) / (double)(k1*k2*k3);
        }
        for(int i = n; i >= 0; --i){
            A[i] = 0.0;
            B[i] = 0.0;
        }
        for(int i = n; i >= 0; --i){
            for(int j = 3; j <= k1+k2+k3; ++j){
                if(i + j > n) continue;
                A[i] += A[i+j] * p[j];
                B[i] += B[i+j] * p[j];
            }
            A[i] += p[0];
            B[i] += 1.0;
    //        printf("A[%d] = %.5lf  B[%d] = %.5lf
    ",i,A[i],i,B[i]);
        }
        printf("%.15lf
    ", (double)(B[0]) / (double)(1.0 - A[0]));
    }
    main(){
    //    freopen(".in","r",stdin);
        T = r;a
        while(T--){
            n = r;
            k1 = r, k2 = r, k3 = r;
            a = r, b = r, c = r;
            Solve();
        }
        return 0;
    }
  • 相关阅读:
    JQ trigger函数无法触发a标签的两种解决方法
    Normalize.css
    wow.js中各种特效对应的类名
    利用伪元素:after清除浮动
    单词超出隐藏显示省略号(单行或多行)并设置是否将单词打断
    利用伪元素和css3实现鼠标移入下划线向两边展开效果
    css3 兼容各个浏览器
    html 初始化
    将博客搬至CSDN
    Linux配置问题
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9346344.html
Copyright © 2011-2022 走看看