ICPC2016 青岛 D - Lucky Coins(概率推公式)

在这里插入图片描述

题意:

给出k类硬币和每类硬币的数量和正面朝上的概率,问每类硬币成为幸运硬币的概率是多少。成为幸运硬币的条件是每投一次将所有背面朝上的硬币去掉,继续抛掷,直至剩下一种或者一个都不剩下,那最后一种留下的硬币就是幸运硬币。

分析:

这题公式推导比较新颖。
一般的划分状态在此题因为状态过多开销巨大而不适用,所以考虑以每次投掷硬币为依据划分阶段。

d i e [ i ] [ j ] die[i][j] die[i][j] 表示第 i i i 类硬币在第 j j j 次投掷(包括第 j j j 次)前就已经被抛弃的概率;
易得: d i e [ i ] [ j ] = ( 1 − p [ i ] j ) n u m [ i ] die[i][j] = (1 - p[i]^j)^{num[i]} die[i][j]=(1p[i]j)num[i]

方便起见,再定一个 a l i v e [ i ] [ j ] alive[i][j] alive[i][j],表示第 i i i 类硬币在第 j j j 次投掷(包括第 j j j 次)后至少有一个硬币还存在的概率;
显然: a l i v e [ i ] [ j ] = 1 − d i e [ i ] [ j ] alive[i][j] = 1 - die[i][j] alive[i][j]=1die[i][j]

i i i 类硬币在第 k k k 轮投掷后成为幸运硬币的概率就是:
a l i v e [ i ] [ k ] × (   ∏ j = 1 , j ≠ i n d i e [ j ] [ k ] − ∏ j = 1 , j ≠ i n d i e [ j ] [ k − 1 ]   ) alive[i][k] \times (\ \prod_{j=1,j \neq i }^{n}{die[j][k] } - \prod_{j=1,j \neq i }^{n}{die[j][k - 1] }\ ) alive[i][k]×( j=1,j=indie[j][k]j=1,j=indie[j][k1] )
其中 (   ∏ j = 1 , j ≠ i n d i e [ j ] [ k ] − ∏ j = 1 , j ≠ i n d i e [ j ] [ k − 1 ]   ) (\ \prod_{j=1,j \neq i }^{n}{die[j][k] } - \prod_{j=1,j \neq i }^{n}{die[j][k - 1] }\ ) ( j=1,j=indie[j][k]j=1,j=indie[j][k1] ) 表示的是其他硬币在第 k − 1 k-1 k1 轮还至少存在一个,到了第 k k k 轮全部被抛弃的概率。

因此第 i i i 类硬币成为幸运硬币的概率就是:
∑ k = 1 ∞ a l i v e [ i ] [ k ] × (   ∏ j = 1 , j ≠ i n d i e [ j ] [ k ] − ∏ j = 1 , j ≠ i n d i e [ j ] [ k − 1 ]   ) \sum_{k=1}^{∞} alive[i][k] \times (\ \prod_{j=1,j \neq i }^{n}{die[j][k] } - \prod_{j=1,j \neq i }^{n}{die[j][k - 1] }\ ) k=1alive[i][k]×( j=1,j=indie[j][k]j=1,j=indie[j][k1] )

这里需要注意特判一下 n = 1 n = 1 n=1 n n n 种硬币) 时即只有 1 1 1 类硬币的情况。

值得推敲的就是求和公式的 ∞ ∞ 符号,真的要取到很大很大,大到无穷项吗? 其实是不需要的,每次投掷硬币有 0.4~0.6 的概率是正面向上,那么当进行几十轮后,这个硬币仍然向上的概率是很小,所以这个求和式很快就收敛了。

因此最终答案就是:
a n s [ i ] = ∑ k = 1 100 a l i v e [ i ] [ k ] × (   ∏ j = 1 , j ≠ i n d i e [ j ] [ k ] − ∏ j = 1 , j ≠ i n d i e [ j ] [ k − 1 ]   ) ans[i] = \sum_{k=1}^{100} alive[i][k] \times (\ \prod_{j=1,j \neq i }^{n}{die[j][k] } - \prod_{j=1,j \neq i }^{n}{die[j][k - 1] }\ ) ans[i]=k=1100alive[i][k]×( j=1,j=indie[j][k]j=1,j=indie[j][k1] )


其实看很多大佬的博客最后答案写的是:
在这里插入图片描述
这个式子表示第 s t e p step step 步时,其他硬币在 1 1 1 s t e p step step 步内死光了,只剩下 i i i 硬币存活,继续扔, i i i 硬币在 s t e p + 1 step+1 step+1 步时死光了。我个人觉得是比较难以理解其中的含义。但是实际上我之前写的式子经过变形后也可以得到这个式子,各位读者可以自行选择理解。

代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 15, M = 105;

double p[N], alive[N][M], die[N][M];
int num[N];

double qmi(double a, int b)
{
    double ans = 1;
    for (; b; b >>= 1)
    {
        if (b & 1) ans = ans * a;
        a = a * a;
    }
    return ans;
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d%lf", &num[i], &p[i]);
        
        if (n == 1) puts("1.000000");
        else
        {
            for (int i = 1; i <= n; i++) // 预处理die, alive
            {
                double P = 1;
                for (int j = 0; j <= 100; j++)
                {
                    die[i][j] = qmi(1 - P, num[i]);
                    alive[i][j] = 1 - die[i][j];
                    P *= p[i];
                } 
            }

            for (int i = 1; i <= n; i++)
            {
                double ans = 0;
                for (int k = 1; k <= 100; k++)
                {
                    double x = 1, y = 1;
                    for (int j = 1; j <= n; j++)
                    {
                        if (j == i) continue;
                        x *= die[j][k];
                        y *= die[j][k - 1];
                    }
                    ans += alive[i][k] * (x - y);
                }
                printf("%.6f", ans);
                if (i == n) printf("\n");
                else printf(" ");
            }
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值