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 Java8 (OpenJDK 1.8.0) (judge verdict: Time Limit Exceeded)

import java.io.*;
import java.util.*;

public class Main {
    static BufferedReader in;
    static HashSet<String> map;

    public static void solve() throws IOException {
        int n = nextInt();
        StringTokenizer st = new StringTokenizer(in.readLine());
        double[] arr = new double[n];
        for(int i = 0;i<n;i++){
            arr[i] = Double.parseDouble(st.nextToken());
        }

        char[] state = new char[n];
        for(int i = 0;i<n;i++){
            state[i] = 'h';
        }
        map = new HashSet<>();
        double ans = recur(arr,state);
        System.out.println(ans);
    }

    static double recur(double[] arr, char[] state){
        String mystate = arrToString(state);
//        System.out.println(mystate);
        if(map.contains(mystate)){
            return 0;
        }

        if(moreT(state)){
            map.add(mystate);
            return 0;
        }

        int n = state.length;
        double tmpAns = sumOfState(arr,state);

        double tmpSum = 0;
        for(int i = 0;i<n;i++){
            if(state[i] == 'h'){
                char[] newChar = Arrays.copyOf(state,n);
                newChar[i] = 't';
                if(!map.contains(arrToString(newChar)))
                    tmpSum +=recur(arr,newChar);
            }
        }
        map.add(mystate);
        return tmpAns+tmpSum;
    }

    static String arrToString(char[] arr){
        StringBuilder ans = new StringBuilder();
        for(char c : arr){
            ans.append(c);
        }

        return ans.toString();
    }
    static double sumOfState(double[] arr, char[] state){
        int n = state.length;
        double mul = 1;
        for (int i = 0; i < n; i++) {
            if(state[i] == 'h'){
                mul*=arr[i];
            }
            else{
                mul*=(1-arr[i]);
            }
        }

        return mul;
    }

    static boolean moreT(char[] state){
        int n = state.length;
        int countT= 0,countH = 0;
        for(char c : state){
            if(c =='t')
                countT++;
            else
                countH++;
        }

        if(countT >= countH)
            return true;
        return  false;
    }

    public static void main(String[] args) throws IOException {
        in = new BufferedReader(new InputStreamReader(System.in));
        solve();
    }

    static int nextInt() throws IOException {
        return Integer.parseInt(in.readLine().trim());
    }

    static long nextLong() throws IOException {
        return Long.parseLong(in.readLine().trim());
    }

    static Integer[] nextArray(int n) throws IOException {
        StringTokenizer st = new StringTokenizer(in.readLine());
        Integer[] tmp = new Integer[n];
        for (int i = 0; i < tmp.length; i++) {
            tmp[i] = Integer.parseInt(st.nextToken());
        }

        return tmp;
    }

}