N 枚硬币,第 i 枚硬币有 pi 的概率正面朝上,有 1−pi 的概率反面朝上。 扔完所有硬币,求正面朝上的银币数比反面朝上的银币数多的概率。
N を正の奇数とします。
N 枚のコインがあります。 コインには 1, 2, …, 1, 2, …, N と番号が振られています。 各 i (1 ≤ i ≤ N) について、コイン i を投げると、確率 pi で表が出て、確率 1 − pi で裏が出ます。
太郎君は N 枚のコインをすべて投げました。 このとき、表の個数が裏の個数を上回る確率を求めてください。
入力は以下の形式で標準入力から与えられる。
N 1p1 2p2 …… pN
表の個数が裏の個数を上回る確率を出力せよ。 絶対誤差が 10−910−9 以下ならば正解となる。
3
0.30 0.60 0.80
0.612
1
0.50
0.5
5
0.42 0.01 0.42 0.99 0.42
0.3821815872
表の個数が裏の個数を上回るような各ケースの確率を計算すると、次のようになります。 - (コイン 1, コイン 2, コイン 3) = (表, 表, 表)(コイン 1, コイン 2, コイン 3) = (表, 表, 表) となる確率は、0.3 × 0.6 × 0.8 = 0.1440.3 × 0.6 × 0.8 = 0.144 である。 - (コイン 1, コイン 2, コイン 3) = (裏, 表, 表)(コイン 1, コイン 2, コイン 3) = (裏, 表, 表) となる確率は、0.7 × 0.6 × 0.8 = 0.3360.7 × 0.6 × 0.8 = 0.336 である。 - (コイン 1, コイン 2, コイン 3) = (表, 裏, 表)(コイン 1, コイン 2, コイン 3) = (表, 裏, 表) となる確率は、0.3 × 0.4 × 0.8 = 0.0960.3 × 0.4 × 0.8 = 0.096 である。 - (コイン 1, コイン 2, コイン 3) = (表, 表, 裏)(コイン 1, コイン 2, コイン 3) = (表, 表, 裏) となる確率は、0.3 × 0.6 × 0.2 = 0.0360.3 × 0.6 × 0.2 = 0.036 である。 よって、表の個数が裏の個数を上回る確率は、0.144 + 0.336 + 0.096 + 0.036 = 0.6120.144 + 0.336 + 0.096 + 0.036 = 0.612 です。
例えば、0.500
, 0.500000001
, 0.499999999
などを出力しても正解となります。
给一堆硬币,求正面比反面多的概率
dp[i][j]表示的是i个硬币时正面硬币是j个的概率
p[i]表示概率
初始化:
dp[1][0]就是第一个是反面,也就是1.0-p[1];
dp[1][1]就是第一个正面,也就是p[1];
当前dp[i][j]的状态由前一个硬币dp[i-1][]得来,前一个硬币有两种状态,正面和反面,对应的概率就是p[i]和 1.0-p[i];
状态转移方程:dp[i][j] = dp[i - 1][j - 1] * p[i] + dp[i - 1][j] * (1.0 - p[i]);
特殊处理:
每个硬币都可能出现全部是反面的情况,状态转移方程中出现了j-1,显然不适合,特判一下即可;
#include
using namespace std;
const int N = 3e3+5;
double p[N];
double dp[N][N];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; ++i)cin >> p[i];
dp[1][1] = p[1];
dp[1][0] = 1.0 - p[1];
for (int i = 2; i <= n; ++i)
for (int j = 0; j <= i; ++j) {
if (j == 0)
{
dp[i][j] = dp[i - 1][j] * (1.0 - p[i]);
continue;
}
dp[i][j] = dp[i - 1][j - 1] * p[i] + dp[i - 1][j] * (1.0 - p[i]);
}
double res = 0;
for (int i = (n + 1) / 2; i <= n; i++) //至少(n+1)/2个正面
res += dp[n][i];
printf("%.10f\n", res);
}