Lucky Coins HDU - 5985(概率)

本文介绍了一种通过多次投掷不同种类硬币并移除背面朝上的硬币,最终确定哪一种硬币为幸运硬币的方法。分析了计算每种硬币成为幸运硬币的概率的算法,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Lucky Coins HDU - 5985

 Bob has collected a lot of coins in different kinds. He wants to know which kind of coins is lucky. He finds out a lucky kind of coins by the following way. He tosses all the coins simultaneously, and then removes the coins that come up tails. He then tosses all the remaining coins and removes the coins that come up tails. He repeats the previous step until there is one kind of coins remaining or there are no coins remaining. If there is one kind of coins remaining, then this kind of coins is lucky. Given the number of coins and the probability that the coins come up heads after tossing for each kind, your task is to calculate the probability for each kind of coins that will be lucky.

Input
The first line is the number of test cases. For each test case, the first line contains an integer k representing the number of kinds. Each of the following k lines describes a kind of coins, which contains an integer and a real number representing the number of coins and the probability that the coins come up heads after tossing. It is guaranteed that the number of kinds is no more than 10, the total number of coins is no more than 1000000, and the probabilities that the coins come up heads after tossing are between 0.4 and 0.6.
Output
For each test case, output a line containing k real numbers with the precision of 6 digits, which are the probabilities of each kind of coins that will be lucky.
Sample Input

3
1
1000000 0.5
2
1 0.4
1 0.6
3
2 0.4
2 0.5
2 0.6

Sample Output

1.000000
0.210526 0.473684
0.124867 0.234823 0.420066
题意:

给你n种硬币,并给你每种硬币的个数和正面朝上的概率。每次将所有的硬币投掷一下。背面朝上的抛弃。直到只剩下一种硬币或者没有硬币。最后剩下的那种硬币叫幸运硬币,问每种硬币成为幸运硬币的概率。

分析:

设两个函数

killed[i][j]=(1pki)nikilled[i][j]=(1−pik)ni

表示第i种硬币到第k步时全部死光

也就是对于一枚i硬币来说正面朝上的概率为pipi,那么k次实验,仍然不死说明k次全部正面朝上,所以是pkipik,然后用1减去就是k步全部死光的概率,共有nini枚硬币,所以根据乘法原理,需要全部乘起来,就得到了上面的公式

recv[i][j]=1killed[i][j]recv[i][j]=1−killed[i][j]

表示第i种硬币到第k步时至少有一个活着,因为我们上面知道了i种硬币到达第k步全部死光的概率,因此用1一减就得到至少一个活着的概率

因此每种硬币i成为幸运硬币的概率,就是对于每一步而言,其他硬币全死光,只剩下i中至少一个存活

ans[i]=maxj=1(recv[i][j]recv[i][j+1])×nk=0,k!=ikilled[k][j]ans[i]=∑j=1max(recv[i][j]−recv[i][j+1])×∏k=0,k!=inkilled[k][j]

上式中的recv[i][j]recv[i][j+1]recv[i][j]−recv[i][j+1]为了确切知道第j步时i硬币存活的概率而避免重复

code:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 75;
const int maxm = 15;
int t,n;
int num[maxm];
double p[maxm];
double killed[maxm][maxn+5];
double recv[maxm][maxn+5];
double ans[maxm];
void solve(){
    int i,j,k;
    for(i = 0; i < maxm; i++){
        ans[i] = 0.0;
    }
    if(n == 1){
        printf("%.6f\n",1.0);
        return;
    }
    for(i = 0; i < n; i++){
        double tmp = p[i];
        for(j = 1; j <= maxn; j++){
            killed[i][j] = pow(1-tmp,num[i]);
            recv[i][j] = 1 - killed[i][j];
            tmp *= p[i];
        }
    }
    for(i = 0; i < n; i++){
        for(j = 1; j < maxn; j++){
            double tmp = 1.0;
            for(k = 0; k < n; k++){
                if(k != i) tmp *= killed[k][j];
            }
            ans[i] += (recv[i][j] - recv[i][j+1]) * tmp;
        }
    }
    for(i = 0; i < n; i++){
        printf("%.6f%c",ans[i],i == n-1 ? '\n' : ' ');
    }
    return;
}
int main(){
    int i;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i = 0; i < n; i++){
            scanf("%d%lf",&num[i],&p[i]);
        }
        solve();
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值