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++ (GCC 9.2.1) (judge verdict: Runtime Error)

    #include <bits/stdc++.h>
    #include <unistd.h>
    //#include <ext/pb_ds/assoc_container.hpp> // Common file
    //#include <ext/pb_ds/tree_policy.hpp> // Including seg_tree_order_statistics_node_update
    #include <stdio.h>
    #include <cassert>
    using namespace std;
    //using namespace __gnu_pbds;
    typedef long long lo;
    typedef long double ld;
    #include <ctime>
    typedef pair<lo, lo> ll; //pair
    typedef vector<lo> vl;   //vector of long
    typedef vector<ll> vll;  //vector of pair
    typedef priority_queue<lo> p_q;
    typedef vector<vl> vvl; //vector of vectors
    #define fastio() ios::sync_with_stdio(0);cin.tie(0)
    #define X first
    #define Y second
    #define mp(a, b) make_pair((a), (b))
    #define REP(a, b) for (lo i = (a); i < (lo)b; i++) //no need to declare variable i
    #define REPE(a, b, c, d) REP(a, b) \
    for (lo j = (c); j < (lo)d; j++)                        //no need to declare vaiables i,j
    #define REPV(a, b, c) for (lo(a) = b; (a) < (c); (a)++) //a is the variable
    #define IREP(a, b) for (lo i = (a); i >= (b); i--)
    #define IREPV(a, b, c) for (lo(a) = b; (a) >= (c); (a)--)
    #define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
    #define all(v) (v).begin(), (v).end()
    #define TRV(a) for (auto &it : a)
    #define INF 500010
    #define MOD 1000000007
    #define M 1000000007
    #define BLOCK 300
    #define CHECK_BIT(var, pos) ((var) & (1 << (pos)))
    #define pb(a) push_back((a))
    #define eps 1e-2
    #define PI acos(-1.0)
    #define _DEBUG 1
    #if _DEBUG
    #define debug(x) cout << #x << "=" << x << endl
    #define debug2(x, y) cout << #x << "=" << x << " " << #y << "=" << y << endl;
    #define debug3(x, y, z) cout << #x << "=" << x << " " << #y << "=" << y << " " << #z << "=" << z << endl;
    #define debug4(x, y, z, w) cout << #x << "=" << x << " " << #y << "=" << y << " " << #z << "=" << z << " " << #w << "=" << w << endl;
    #define debug5(x, y, z, w, t)      \
        cout << #x << "=" << x << " "; \
        debug4(y, z, w, t);
    #define debug6(p, x, y, z, w, t)                            \
        cout << #p << " " << p << " " << #x << "=" << x << " "; \
        debug4(y, z, w, t);
    #define debug7(o, p, x, y, z, w, t) \
        cout << #o << " " << o << " ";  \
        debug6(p, x, y, z, w, t);
    #define wait  \
        int xxxx; \
        cin >> xxxx;
    #define derr(x) cerr << #x << "=" << x << endl;
    #define derr2(x, y) cerr << #x << "=" << x << " " << #y << "=" << y << endl;
    #define derr3(x, y, z) cerr << #x << "=" << x << " " << #y << "=" << y << " " << #z << "=" << z << endl;
    #define derr4(x, y, z, w) cerr << #x << "=" << x << " " << #y << "=" << y << " " << #z << "=" << z << " " << #w << "=" << w << endl;
    #define derr5(x, y, z, w, t)       \
        cerr << #x << "=" << x << " "; \
        derr4(y, z, w, t);
    #define derr6(p, x, y, z, w, t)                             \
        cerr << #p << " " << p << " " << #x << "=" << x << " "; \
        derr4(y, z, w, t);
    #define derr7(o, p, x, y, z, w, t) \
        cerr << #o << " " << o << " "; \
        derr6(p, x, y, z, w, t);
    lo checkpoint_counter=0;
    #define checkpoint cerr << "At checkpoint : " << checkpoint_counter++ << endl;

    #else
    #define debug(x) ;
    #define debug2(x, y) ;
    #define debug3(x, y, z) ;
    #define debug4(x, y, z, q) ;
    #define debug5(x, y, z, r, t) ;
    #define debug6(x, y, z, r, t, s) ;
    #define debug7(x, y, z, r, t, s, u) ;
    #define wait ;
    #define derr(x) ;
    #define derr2(x, y) ;
    #define derr3(x, y, z) ;
    #define derr4(x, y, z, q) ;
    #define derr5(x, y, z, r, t) ;
    #define derr6(x, y, z, r, t, s) ;
    #define derr7(x, y, z, r, t, f, u) ;
    #define checkpoint ;
    #endif

    #define print_matrix(a, n, m) \
        REPE(0, n, 0, m) { cout << (a)[i][j] << ((j == m - 1) ? '\n' : ' '); }
    #define present(container, element) (container.find(element) != container.end())
    #define endl "\n"
    #define add(a) accumulate(all(a), lo(0));
    #define add(a, x) accumulate(all(a), x);
    template <typename T>
    ostream &operator<<(ostream &o, vector<T> v)
    {
        if (v.size() > 0)
            o << v[0];
        for (unsigned i = 1; i < v.size(); i++)
            o << " " << v[i];
        return o << " ";
    }
    template <typename U, typename V>
    ostream &operator<<(ostream &o, pair<U, V> p)
    {
        return o << "(" << p.first << ", " << p.second << ") ";
    }
    template <typename T>
    istream &operator>>(istream &in, vector<T> &v)
    {
        for (unsigned i = 0; i < v.size(); i++)
            in >> v[i];
        return in;
    }
    template <typename T>
    istream &operator>>(istream &in, pair<T, T> &p)
    {
        in >> p.X;
        in >> p.Y;
        return in;
    }
    template <typename T>
    ostream &operator<<(ostream &o, set<T> v)
    {
        TRV(v)
            o << it << " ";
        return o << endl;
    }
    template <typename T, typename U>
    ostream &operator<<(ostream &o, map<T, U> v)
    {
        TRV(v)
            o << it << " ";
        return o << endl;
    }
    struct custom_hash
    {
        static uint64_t splitmix64(uint64_t x)
        {
            // http://xorshift.di.unimi.it/splitmix64.c
            x += 0x9e3779b97f4a7c15;
            x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
            x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
            return x ^ (x >> 31);
        }

        size_t operator()(uint64_t x) const
        {
            static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
            return splitmix64(x + FIXED_RANDOM);
        }
    };

    
    lo tree[1000100]={0};

    void build(lo node, lo start, lo end)
    {
        if(start == end)
        {
            tree[node] = 0;
        }
        else
        {
            lo mid = (start + end) / 2;
            build(2*node+1, start, mid);
            build(2*node+2, mid+1, end);
            tree[node] = min(tree[2*node+1], tree[2*node+2]);
        }
    }

    void update(lo node, lo start, lo end, lo idx, lo val)
    {
        if(start == end)
        {
            // Leaf node
            //cout<<start<<" "<<end<<" "<<tree[node]<<endl;
            tree[node] = val;
        }
        else
        {
            lo mid = (start + end) / 2;
            if(start <= idx and idx <= mid)
            {
                // If idx is in the left child, recurse on the left child
                update(2*node+1, start, mid, idx, val);
            }
            else
            {
                // if idx is in the right child, recurse on the right child
                update(2*node+2, mid+1, end, idx, val);
            }
            // Internal node will have the sum of both of its children
            tree[node] = min(tree[2*node+1], tree[2*node+2]);
            //cout<<start<<" "<<end<<" "<<tree[node]<<endl;
        }
    }

    lo query(lo node, lo start, lo end, lo l, lo r)
    {
        if(r < start or end < l)
        {
            // range represented by a node is completely outside the given range
            return 0;
        }
        
        if(l <= start and end <= r)
        {
            //cout<<start<<" "<<end<<" "<<tree[node]<<endl;
            // range represented by a node is completely inside the given range
            return tree[node];
        }
        // range represented by a node is partially inside and partially outside the given range
        lo mid = (start + end) / 2;
        lo p1 = query(2*node+1, start, mid, l, r);
        lo p2 = query(2*node+2, mid+1, end, l, r);
        return min(p1, p2);
    }

bool cmp(ll a, ll b){
        if(a.X == b.X)return a.Y < b.Y;
        return a.X < b.X;
    }


int main(){
    lo t;
    //cin>>t;
    t=1;
    while(t--){
        lo n,a,b;
        ld te;
        cin>>n;
        vector<ld> p;
        ld dp[3010][3010]={0.0}, mi[3010][3010]={0.0};
        REP(0,n){
            cin>>te;
            p.pb(te);
        }
        mi[0][1]=1.0-p[0];
        mi[0][0]=0;
        dp[0][0]=0;
        dp[0][1]=p[0];
        REP(1,n){
            if((i+1)%2==0){
                for(lo j=2;j<=i+1;j+=2){
                    dp[i][j]=dp[i-1][j-1]*p[i] + dp[i-1][j+1]*(1.0-p[i]);
                    mi[i][j]=mi[i-1][j-1]*(1-p[i])+mi[i-1][j+1]*(p[i]);
                }
                dp[i][0]=dp[i-1][1]*(1.0-p[i])+mi[i-1][1]*(p[i]);
                mi[i][0]=dp[i][0];
            }else{
                for(lo j=1;j<=i+1;j+=2){
                    dp[i][j]=dp[i-1][j-1]*p[i] + dp[i-1][j+1]*(1.0-p[i]);
                    mi[i][j]=mi[i-1][j-1]*(1-p[i])+mi[i-1][j+1]*(p[i]);
                }
            }
        }
        /*REP(0,n){
            REPV(j,0,n+1)cout<<dp[i][j]<<" ";
            cout<<endl;
        }*/
        ld ans=0;
        REP(1,n+1)ans+=dp[n-1][i];
        cout<<fixed<<setprecision(10)<<ans;
    }
    return 0;
}