• CodeForces


    题目

    传送门

    解法

    (dp_{i,j}) 为识别前 (i) 首歌,需要 (j) 秒的概率(为什么会在后面提及)。容易想到枚举第 (i) 首歌已经听了 (k) 秒来转移:

    [dp_{i,j}=sum_{k=1}^{t_i-1}dp_{i-1,j-k} imes (1-p_i)^{k-1} imes p_i ]

    这是 (mathcal O(n^3)) 的。但是这个方程的 (k) 在指数上,也就是说,不同的 (j) 会引起系数的 整体 变化!具体地说,考虑 (dp_{i,j-1})(dp_{i,j}) 的变化:在 (j-1)(kin[1,t_i-1]),转移到 (j) 相当于 (kin[2,t_i])。于是我们需要补 (k=1) 那一项,还要去除 (t_i) 那一项。这样复杂度降到了 (mathcal O(n^2))

    每首歌的贡献为 (1),所以直接将概率相加即可。

    代码

    #include <cstdio>
    
    const int N = 5005;
    
    int n, T, t[N];
    double p[N], f[N][N], ans;
    
    int read() {
        int x = 0, f = 1; char s;
        while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
        while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
        return x * f;
    }
    
    double qkpow(double x, int y) {
        double r = 1;
        while(y) {
            if(y & 1) r *= x;
            x *= x; y >>= 1;
        }
        return r;
    }
    
    int main() {
        n = read(), T = read();
        for(int i = 1; i <= n; ++ i) p[i] = 1.0 * read() / 100, t[i] = read();
        f[0][0] = 1;
        for(int i = 1; i <= n; ++ i) {
            double sum = 0, w = qkpow(1 - p[i], t[i] - 1);
            for(int j = 1; j <= T; ++ j) {
                sum *= 1 - p[i];
                sum += f[i - 1][j - 1] * p[i];
                if(j >= t[i]) {
                    sum -= f[i - 1][j - t[i]] * w * p[i];
                    f[i][j] += f[i - 1][j - t[i]] * w;
                }
                f[i][j] += sum; ans += f[i][j];
            }
        }
        printf("%.9f
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    convex hull
    不努力,你就没有资格谈天赋
    “数数”的感悟
    平行四边形法则的感悟
    ansys 15 Linux 安装问题
    SHV-E210S 刷4.3
    fedora 安装 Oracle11g 遇到的问题
    ObjectArx开发常用资料
    MFC入门(二)
    MFC入门(三)
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/12679930.html
Copyright © 2020-2023  润新知