1. 程式人生 > >atcoderI - Coins ( 概率DP)

atcoderI - Coins ( 概率DP)

HERE with print sed return times sid algorithm pos

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.500, 0.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), ‘\0‘, 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\n", ans);
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch ==   || ch == \n);
    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;
        }
    }
}

atcoderI - Coins ( 概率DP)