Problem:
Score : 100 points

Problem Statement

Let N be a positive odd number.

There are N coins, numbered 1, 2, \ldots, N.
For each i (1 \leq i \leq N), when Coin i is tossed, it comes up heads with probability p_i and tails with probability 1 - p_i.

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

Constraints

N is an odd number.

1 \leq N \leq 2999

p_i is a real number and has two decimal places.

0 < p_i < 1

Input

Input is given from Standard Input in the following format:

N
p_1 p_2 \ldots p_N

Output

Print the probability of having more heads than tails.
The output is considered correct when the absolute error is not greater than 10^{-9}.

Sample Input 1

3
0.30 0.60 0.80

Sample Output 1

0.612

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

The probability of having (Coin 1, Coin 2, Coin 3) = (Head, Head, Head) is 0.3 × 0.6 × 0.8 = 0.144;

The probability of having (Coin 1, Coin 2, Coin 3) = (Tail, Head, Head) is 0.7 × 0.6 × 0.8 = 0.336;

The probability of having (Coin 1, Coin 2, Coin 3) = (Head, Tail, Head) is 0.3 × 0.4 × 0.8 = 0.096;

The probability of having (Coin 1, Coin 2, Coin 3) = (Head, Head, Tail) is 0.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.612.

Sample Input 2

1
0.50

Sample Output 2

0.5

Outputs such as 0.500, 0.500000001 and 0.499999999 are also considered correct.

Sample Input 3

5
0.42 0.01 0.42 0.99 0.42

Sample Output 3

0.3821815872

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include "iostream"
#include "fstream"
#include "algorithm"
#include "iomanip"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "map"
#include "set"
#include "unordered_set"
#include "unordered_map"
#include "iterator"
#include <ctime>
#include "bitset"
#include "cmath"
#include "list"
#include "complex"
#include <cassert>
#include "deque"
#include "numeric"
#include <cstdio>

using namespace std;

//#define f(i,n) for(int i=0; i<n;i++) 
//#define rf(i, n) for(int i=n-1;i>=0;i--)
//#define forn(i, j, n) for(int i=j; i<n; i++)
//#define ff(i, j, n) f(i, n)f(j, n)
#define pb push_back
//#define mp make_pair
#define maxi(a,b) a = max(a, b);
#define mini(a,b) a = min(a, b);
#define endl '\n'
#define all(a) a.begin(), a.end()
#define sqr(x) ((x) * (x))
#define SZ(a) ((int)(a.size()))
#define watch(x) cout << (#x) << " = " << x << endl;
//typedef long long ll;
typedef long double ld;
#define int long long
#define double ld
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef pair<string, int> psi;
typedef pair<int, string> pis;
typedef vector<int> vi;
typedef vector<double> vd;
typedef vector<pii> vpii;
typedef vector<char> vc;

template<class T>
void show(const vector<T> &a)
{
	for (T x : a)
		cout << x << " ";
	cout << endl;
}

const int sze = 3e5 + 50, oo = 1e18 + 500, mod = 1e9 + 7;
const double eps = 1e-9, PI = 2 * acos(0.0);
vi vertices[sze];
vc visit(sze, false);
vc used(sze, false);
vi arr(sze, 0);
int n, m, k;
int A, B;
int cnt = 0;

//struct edge
//{
//	int from, to, flow, cap;
//};
//
//vector<edge> e;
//
//void add_edge(int from, int to, int flow, int cap)
//{
//	edge e1 = { from, to, 0, 1 };
//	edge e2 = { to, from, 0, 0 };
//	vertices[from].pb(e.size());
//	e.pb(e1);
//	vertices[to].pb(e.size());
//	e.pb(e2);
//}
//
//int ptr[sze];
//int d[sze];
//int s;
//int t;
//
//bool bfs()
//{
//	queue<int> q;
//	fill(d, d+n+10, -1);
//	d[s] = 0;
//	while (!q.empty())
//	{
//		int v = q.front();
//		q.pop();
//
//		for (auto id : vertices[v])
//		{
//			int to = e[id].to;
//
//			if (d[to] = -1 && e[id].flow < e[id].cap)
//			{
//				d[to] = d[v] + 1;
//				q.push(to);
//			}
//		}
//	}
//
//	return d[t] != -1;
//}
//
//int dfs(int v, int flow)
//{
//	if (!flow || v == t)
//		return flow;
//
//	for (; ptr[v] < vertices[v].size(); ptr[v]++)
//	{
//		int id = vertices[v][ptr[v]];
//		int to = e[id].to;
//
//		if (d[to] != d[v] + 1)
//		{
//			continue;
//		}
//
//		int pushed = dfs(to, min(flow, e[id].cap - e[id].flow));
//		if (pushed)
//		{
//			e[id].flow += pushed;
//			e[id ^ 1].flow -= pushed;
//			return pushed;
//		}
//	}
//	return 0;
//}
//
//int dinic()
//{
//	int flow = 0;
//	while (bfs())
//	{
//		fill(ptr, ptr + n + 10, 0);
//		while (int pushed = dfs(s, oo))
//		{
//			flow += pushed;
//		}
//	}
//
//	return flow;
//}

double dp[3010][3010];

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	cin >> n;
	vd p(n+10);

	for (int i = 1; i <= n; i++)
	{
		cin >> p[i];
	}

	dp[0][0] = 1.0;
	
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j <= i; j++)
		{
			dp[i + 1][j] += dp[i][j] * (1 - p[i + 1]);
			dp[i + 1][j + 1] += dp[i][j] * p[i + 1];
		}
	}

	double ans = 0;
	for (int j = n / 2 + 1; j <= n; j++)
	{
		ans += dp[n][j];
	}

	cout << fixed << setprecision(10) << ans;
	
	return 0;
}