Problem: You are given a rooted tree. Let's denote d(x) as depth of node x: depth of the root is 1, depth of any other node x is d(y) + 1, where y is a parent of x.

The tree has the following property: every node x with d(x) = i has exactly ai children. Maximum possible depth of a node is n, and an = 0.

We define fk as the number of unordered pairs of vertices in the tree such that the number of edges on the simple path between them is equal to k.

Calculate fk modulo 109 + 7 for every 1 ≤ k ≤ 2n - 2.

Input

The first line of input contains an integer n (2 ≤ n ≤ 5 000) — the maximum depth of a node.

The second line of input contains n - 1 integers a1, a2, ..., an - 1 (2 ≤ ai ≤ 109), where ai is the number of children of every node x such that d(x) = i. Since an = 0, it is not given in the input.

Output

Print 2n - 2 numbers. The k-th of these numbers must be equal to fk modulo 109 + 7.

Examples

Input

4
2 2 2


Output

14 19 20 20 16 16 

Input

3
2 3


Output

8 13 6 9 

Note

This the tree from the first sample: 

<image>

Solution (in JAVA):

Solution:
import java.io.*;
import java.util.*;

public class A {
	public static void main (String[] args) { new A(); }

	int MOD = (int)1e9+7;
	
	public A() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt();
		int[] kids = new int[n];
		for(int i = 0; i < n-1; i++) kids[i] = fs.nextInt();
		
		int[][] walkDown = new int[n][n];
		int[][] walkDown2 = new int[n][n];
		
		for(int i = 0; i < n; i++) {
			int prod = 1, prod2 = 1;
			for(int j = 1; j < n; j++) {
				if(i + j - 1 >= n) break;
				
				if(j == 1) prod2 = mult(prod2, Math.max(0, kids[i + j - 1] - 1));
				else prod2 = mult(prod2, kids[i + j - 1]);
				
				prod = mult(prod, kids[i + j - 1]);
				
				walkDown[i][j] = prod;
				walkDown2[i][j] = prod2;
			}
		}
		
		for(int j = 0; j < n; j++) {
			for(int d = 1; ; d++) {
				int row = 0+d;
				int col = j+d;
				if(row >= n || col >= n) break;
				
				walkDown2[row][col] = add(walkDown2[row][col], walkDown2[row-1][col-1]);
			}
		}
		for(int i = 1; i < n; i++) {
			for(int d = 1; ; d++) {
				int row = i+d;
				int col = 0+d;
				if(row >= n || col >= n) break;
				
				walkDown2[row][col] = add(walkDown2[row][col], walkDown2[row-1][col-1]);
			}
		}
		
		int[] freq = new int[n];
		freq[0] = 1;
		for(int i = 1; i < n; i++) {
			freq[i] = mult(freq[i-1], kids[i-1]);
		}
		
		int[] totWays = new int[2 * n];
		
		for(int kid = n-1; kid >= 0; kid--) {
			for(int dist = 1; dist <= 2 * n - 2; dist++) {
				int tot = 0;
				
				if(dist < n) tot = add(tot, walkDown[kid][dist]);
				
				if(kid > 0) {
					int row = kid-1, col = dist-1;
					if(row >= n || col >= n) {
						int d = Math.max(row-n+1, col-n+1);
						row -= d;
						col -= d;
					}
					int finRow = kid-dist, finCol = 0;
					if(finRow < 0) {
						int add = -finRow;
						finRow += add;
						finCol += add;
					}
					
					if(row >= finRow) {
						int x = walkDown2[row][col];
						if(finRow > 0 && finCol > 0) {
							x -= walkDown2[finRow-1][finCol-1];
						}
						tot = add(tot, x);
					}
				}
				
//				System.out.println(kid + " " + dist + " " + tot);
				if(kid-dist >= 0) tot = add(tot, 1);
				
				totWays[dist] = add(totWays[dist], mult(tot, freq[kid]));
			}
//			System.out.println();
		}
		
		int INV2 = (MOD+1)/2;
		
		for(int i = 0; i < totWays.length; i++) {
			totWays[i] = mult(totWays[i], INV2);
		}
		
		for(int i = 1; i <= 2 * n - 2; i++) {
			if(i > 1) out.print(" ");
			out.print(totWays[i]);
		}
		out.println();
		
		out.close();
	}
	
	int add(int a, int b) {
		a += b;
		if(a >= MOD) a -= MOD;
		return a;
	}
	
	int mult(long a, long b) {
		return (int)(a * b % MOD);
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}                
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}
		
		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}
		
	}

}