HDU-5985 Lucky Coins (概率)

题目链接:HDU-5985 Lucky Coins

题意

给出 n 种硬币,已知每种硬币的个数和抛掷后正面朝上的概率,每次将所有硬币抛掷,背面朝上的丢弃,直到只剩下一种硬币被称为幸运硬币,问每种硬币成为幸运硬币的概率。


思路

\(f[i][k]\) 表示第 \(i\) 种硬币第 \(k\) 轮之后全无剩下的概率,\(p_i\) 表示第 \(i\) 种硬币正面朝上的概率,\(n_i\) 表示第 \(i\) 种硬币的个数,则 \(f[i][k] = (1-p_i^k)^{n_i}\)

\(g[i][k]\) 表示第 \(i\) 种硬币第 \(k\) 轮之后至少还剩下一个的概率,显然 \(g[i][k] = 1-f[i][k]\)

\(ans[i]\) 表示第 \(i\) 种硬币成为幸运硬币的概率,则

\[ans[i] = \sum_{k=0}^\infty(g[i][k]-g[i][k+1])\prod_{j=1,j\ne i}^nf[j][k] \]

后面的连乘表示除了第 \(i\) 种硬币外,其他的硬币在第 \(k\) 轮之后全无剩下的概率,\(g[i][k]-g[i][k+1]\) 表示第 \(i\) 种硬币在第 \(k\) 轮之后还有剩下,在第 \(k+1\) 轮之后全无剩下的概率,即恰好在第 \(k\) 轮之后成为幸运硬币的概率。如果没有减去 \(g[i][k+1]\) ,意义是在第 \(k\sim \infty\) 轮之后成为幸运硬币的概率,后面再算 \(k+1\sim \infty,k+2\sim \infty...\) 轮,会重复计算。

本题中给定的概率值在 0.4~0.6 之间,当硬币投掷次数很多时,几乎不会对后面的概率产生影响,所以选择能够不超时间空间的近似无穷大值作为 \(k\) 值的上界即可。


代码实现

#include <cstdio>
double f[11][1010];
double qpow(double a, int b) {
    double res = 1;
    while (b) {
        if (b & 1) res = res * a;
        b >>= 1;
        a *= a;
    }
    return res;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, ni, mxk = 1000;
        double pi;
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            scanf("%d %lf", &ni, &pi);
            double pik = 1;
            for (int k = 0; k < mxk; k++, pik *= pi) {
                f[i][k] = qpow(1 - pik, ni);
            }
        }
        for (int i = 0; i < n; i++) {
            double ans = 0;
            for (int k = 0; k < mxk - 1; k++) {
                double tmp = 1;
                for (int j = 0; j < n; j++) {
                    if (j == i) continue;
                    tmp *= f[j][k];
                }
                ans += (f[i][k+1] - f[i][k]) * tmp;
            }
            printf("%.6f%c", ans, " \n"[i==n-1]);
        }
    }
    return 0;
}
posted @ 2020-05-17 22:11  _kangkang  阅读(141)  评论(0编辑  收藏  举报