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的TreeMap,C++的lower_bound,合并间隔
    最多包含2/k个不同字符的最长串
    爆气球这道题目,展开了新的思路
    C++的hashmap和Java的hashmap
    求数组里重复出现的数字
    数组中出现一次的两个数(三个数)& 求最后一位bit为1
    皇后问题的经典做法
    海外省电应用市场:本土化为先锋,高技术为基础
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/10280057.html
Copyright © 2011-2022 走看看