zoukankan      html  css  js  c++  java
  • atcoderI

    I - Coins


    Time Limit: 2 sec / Memory Limit: 1024 MB

    Score : 100100 points

    Problem Statement

    Let NN be a positive odd number.

    There are NN coins, numbered 1,2,,N1,2,…,N. For each ii (1iN1≤i≤N), when Coin ii is tossed, it comes up heads with probability pipi and tails with probability 1pi1−pi.

    Taro has tossed all the NN coins. Find the probability of having more heads than tails.

    Constraints

    • NN is an odd number.
    • 1N29991≤N≤2999
    • pipi is a real number and has two decimal places.
    • 0<pi<10<pi<1

    Input

    Input is given from Standard Input in the following format:

    NN
    p1p1 p2p2  pNpN
    

    Output

    Print the probability of having more heads than tails. The output is considered correct when the absolute error is not greater than 10910−9.


    Sample Input 1 Copy

    Copy
    3
    0.30 0.60 0.80
    

    Sample Output 1 Copy

    Copy
    0.612
    

    The probability of each case where we have more heads than tails is as follows:

    • The probability of having (Coin1,Coin2,Coin3)=(Head,Head,Head)(Coin1,Coin2,Coin3)=(Head,Head,Head) is 0.3×0.6×0.8=0.1440.3×0.6×0.8=0.144;
    • The probability of having (Coin1,Coin2,Coin3)=(Tail,Head,Head)(Coin1,Coin2,Coin3)=(Tail,Head,Head) is 0.7×0.6×0.8=0.3360.7×0.6×0.8=0.336;
    • The probability of having (Coin1,Coin2,Coin3)=(Head,Tail,Head)(Coin1,Coin2,Coin3)=(Head,Tail,Head) is 0.3×0.4×0.8=0.0960.3×0.4×0.8=0.096;
    • The probability of having (Coin1,Coin2,Coin3)=(Head,Head,Tail)(Coin1,Coin2,Coin3)=(Head,Head,Tail) is 0.3×0.6×0.2=0.0360.3×0.6×0.2=0.036.

    Thus, the probability of having more heads than tails is 0.144+0.336+0.096+0.036=0.6120.144+0.336+0.096+0.036=0.612.


    Sample Input 2 Copy

    Copy
    1
    0.50
    

    Sample Output 2 Copy

    Copy
    0.5
    

    Outputs such as 0.5000.500000001 and 0.499999999 are also considered correct.


    Sample Input 3 Copy

    Copy
    5
    0.42 0.01 0.42 0.99 0.42
    

    Sample Output 3 Copy

    Copy
    0.3821815872

    double p[maxn];
    double dp[3050][3050];
    int n;

    题意:给N个硬币,每一个硬币扔向空中落地是正面朝上的概率是p[i] ,让求扔了N个硬币,正面的数量大于背面数量的概率。
    很裸的概率DP,我们思考一下状态和转移方程。
    我们这样定义状态,定义dp[i][j] 为到第i个硬币时有j个是正面的概率。那么所求答案为sum{ dp[n][i] || (n+1)/2<=i<=n}
    题目说了n为odd,
    那么状态转移即为: dp[i][j]=dp[i-1][j-1]*p[i]+dp[i-1][j]*(1.0-p[i]);
    意思为,到了第i个硬币时,j个正面朝上的状态可以由以下两个状态转移过来:
    1、第i-1个硬币的时候,有j-1个正面朝上的,第i个硬币也正面朝上。
    2、
    第i-1个硬币的时候,有j个正面朝上的,第i个硬币反面朝上。
    然后初始状态定义

      

    dp[1][1]=p[1];
    dp[1][0]=1.0000000-p[1];

    注意处理下边界情况就好了。

    细节见AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    using namespace std;
    typedef long long ll;
    inline void getInt(int* p);
    const int maxn=1000010;
    const int inf=0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    double p[maxn];
    double dp[3050][3050];
    int n;
    int main()
    {
        gg(n);
        repd(i,1,n)
        {
            scanf("%lf",&p[i]);
        }
        dp[1][1]=p[1];
        dp[1][0]=1.0000000-p[1];
    
        repd(i,2,n)
        {
            for(int j=0;j<=i;j++)
            {
                if(j==0)
                {
                    dp[i][j]=dp[i-1][j]*(1.00000-p[i]);
                    continue;
                }
                dp[i][j]=dp[i-1][j-1]*p[i]+dp[i-1][j]*(1.0000-p[i]);
    //            dp[i][j-1]=dp[i-1][j-1]*(1.000000-p[i]);
            }
        }
        double ans=0.0000000000000000000;
        for(int i=(n+1)/2;i<=n;i++)
        {
            ans+=dp[n][i];
        }
        printf("%.10lf
    ", ans);
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }

    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    Java for LeetCode 229 Majority Element II
    Java for LeetCode 228 Summary Ranges
    Java for LeetCode 227 Basic Calculator II
    Java for LintCode 颜色分类
    Java for LintCode 链表插入排序
    Java for LintCode 颠倒整数
    Java for LintCode 验证二叉查找树
    Java for LeetCode 226 Invert Binary Tree
    Java for LeetCode 225 Implement Stack using Queues
    Java for LeetCode 224 Basic Calculator
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/10280057.html
Copyright © 2011-2022 走看看