coins - atcoder contest
I - Coins
educational dynamming programming contest
coins
There’s n coins, and 2^n possible flip sequences. There’s a closed form expression for this when the probability of the coins being heads is the same for all coins. That is not the case here.
The probability of a sequence of independent flips is the product of each flip’s proability (p_i if heads and (1 - p_i) if tails).
You could sum up all of those products in which there’s more heads than tails (# heads >= n/2 + 1). However, n < 3000, and there’s (n choose (n/2 + 1)) of these products.
Notice that these products can share segments:
P(H1 T2 H3 T4 H5) = P(H1 T2 H3 T4) * P(H5)
P(H1 T2 H3 T4 T5) = P(H1 T2 H3 T4) * P(T5)
A very intuitive dynammic programming solution follows:
dp[i][j] = P(getting i heads in first j flips) = P(Hj) * P(getting i - 1 heads in the first j - 1 flips) + P(Tj) * P(getting i heads in the first j - 1 flips)
my submission
#include<iostream>
#include<iomanip>
using namespace std;
int n;
long double P[3000];
long double dp[3000][3000];
int main() {
cin >> n;
for (int i = 1;i < n + 1;++i) cin >> P[i];
dp[0][0] = 1;
for (int flips = 1;flips < n + 1;++flips)
dp[0][flips] = (1.0 - P[flips]) * dp[0][flips - 1];
for (int flips = 1;flips < n + 1;++flips) {
for (int heads = 1;heads <= flips;++heads) {
dp[heads][flips] = P[flips] * dp[heads - 1][flips - 1] + (1 - P[flips]) * dp[heads][flips - 1];
}
}
long double more_heads = 0;
for (int heads = n/2 + 1;heads < n + 1;++heads) more_heads += dp[heads][n];
cout << std::setprecision(9) << more_heads << endl;
}