码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5985 Lucky Coins 概率dp

时间:2018-09-21 23:17:14      阅读:363      评论:0      收藏:0      [点我收藏+]

标签:algorithm   状态   make   algo   end   数字   表示   printf   一个   

题意:给你N种硬币,每种硬币有Si个,有Pi 概率朝上,每次抛所有硬币抛起,所有反面的拿掉,问每种硬币成为最后的lucky硬币的概率。

题解:都知道是概率dp,但是模拟赛时思路非常模糊,很纠结,dp[10][1e6]这个状态让我觉得丝毫没有用,当时一直以为每种硬币是互相独立的。然后中间吃了个饭,回来又想了很久很久,就是不想看题解,然后发现,这个dp和极限有关,同时状态跟走了几步有极大的关系。否则你初始值根本没法赋,那么显然我猜既然保留6位,肯定当数字小到一定程度时是可以忽略的,也就是进行的次数多了后。随意打了个表,0.6的36次小于1e-8,然而事实是这样还不够。好像要开到70多。然后就定义一个dp1[i][j]=(1-pij )^num[i]为进行了j轮后第i种硬币全无的概率(表示不看题解这个式子怎么算都不知道),那么1-dp1[i][j]就是还活着的概率。那么这个问题也就变成了第j轮后网上很多题解的那个式子

ans[i]=∑1~max (dp2[i][j]-dp2[i][j+1])*∏k!=i  dp1[k][j]   我没考虑到的主要是要减掉 dp2[i][j+1],因为这里相当于是在第j这个位置就要结束游戏,所以要剪掉下一步还存活的概率。稍微还是有点不理解,概率题好难想啊。

#include<cstdio>
#include<iostream>
#include<bitset>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#define mp make_pair
#define pb push_back
#define ll long long
#define lc no[x].ch[0]
#define rc no[x].ch[1]
#define pa no[x].fa
#define db double
#define ls x<<1
#define rs x<<1|1
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Forr(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=80;

int num[20];
double num1[20];
double dp1[20][100];
double dp2[20][100];
double ans[20];
int n;
double q_pow(db vs,int t)
{
    double res=1.0;
    while(t)
    {
        if(t&1)
        {
            res*=vs;
        }
        vs=vs*vs;
        t>>=1;
    }
    return res;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%lf",&num[i],&num1[i]);
        }
        for(int i=1;i<=n;i++)
        {
            ans[i]=0.0;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<maxn;j++)
            {
                double st=q_pow(num1[i],j);
               // cout<<st<<endl;
                dp1[i][j]=q_pow(1-st,num[i]);
                dp2[i][j]=1-dp1[i][j];
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<maxn;j++)
            {
                double tmp=1.0;
                for(int k=1;k<=n;k++)
                {
                    if(k!=i)tmp*=dp1[k][j];
                }
                ans[i]+=(dp2[i][j]-dp2[i][j+1])*tmp;
            }
        }
        if(n==1){printf("%.6f\n",1.0);continue;}
        for(int i=1;i<n;i++)
        {
            printf("%.6f ",ans[i]);
        }printf("%.6f\n",ans[n]);
    }
}

 

HDU5985 Lucky Coins 概率dp

标签:algorithm   状态   make   algo   end   数字   表示   printf   一个   

原文地址:https://www.cnblogs.com/intwentieth/p/9688611.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!