D - Lucky Coins(概率)

题意:
给出n种硬币和他们的数量还有他们掷出正面朝上的概率,每一轮会投掷场上的所有硬币,只有正面朝上的硬币会留在场上,反面的硬币会被淘汰。求对于每种硬币只有他们最后能留在场上的概率。(Problem - 5985 (hdu.edu.cn)

分析:
给出的概率在0.4-0.6之间,可以想象到这个投掷次数一多对答案的影响可以忽略不计,然后给出的硬币虽然数量在1e6内,但是种类只有10以内,所以我们可以模拟对于每种硬币进行投掷,一直投掷到他们全部淘汰为止。

对于每种硬币,设他们数量为c,正面朝上的概率为p,那么他们在第n轮就全部淘汰的概率为(1-p^{c})^{n}

f[i][j]表示第i中硬币刚好在第j轮全部淘汰的概率,我们模拟1000轮。算出每种硬币没有被淘汰的概率然后其他硬币都被淘汰的概率累乘起来就是这种硬币最后能留在场上的概率。

需要注意的是,(1-f[i][j])表示这种硬币在第j轮至少还剩下一个硬币的概率,但是他不能表示仅在第j轮有剩的概率,因为他可能包含了后面轮数还有剩的概率,所以我们要想表示他仅在第j轮有剩的概率还要减去(1-f[i][j+1])

贴上代码:
 

#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define endl '\n'
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
double f[20][1200];
int a[20];
double p[20];
double qmi(double a, int b)
{
    double res = 1;
    while (b)
    {
        if (b & 1)
            res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}
void solve()
{
    int n;
    cin >> n;
    memset(f, 0, sizeof(f));
    memset(a, 0, sizeof(a));
    memset(p, 0, sizeof(p));
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i] >> p[i];
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= 1000; j++)
        {
            double t = qmi(p[i], j);
            t = 1 - t;
            f[i][j] = qmi(t, a[i]);
        }
    }
    for (int i = 1; i <= n; i++)
    {
        double res = 0;
        for (int j = 0; j < 1000; j++)
        {
            double huo1 = 1 - f[i][j];
            double huo2 = 1 - f[i][j + 1];
            double sum = 1;
            for (int k = 1; k <= n; k++)
            {
                if (k == i)
                    continue;
                sum *= f[k][j];
            }
            sum *= (huo1 - huo2);
            res += sum;
        }
        cout << fixed << setprecision(6) << res;
        if (i != n)
            cout << " ";
    }
    cout << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值