Programming teacher Dmitry Olegovich is going to propose the following task for one of his tests for students:

You are given a tree T with n vertices, specified by its adjacency matrix a[1... n, 1... n]. What is the output of the following pseudocode?
    
    
      
    used[1 ... n] = {0, ..., 0};  
      
    procedure dfs(v):  
        print v;  
        used[v] = 1;  
        for i = 1, 2, ..., n:  
            if (a[v][i] == 1 and used[i] == 0):  
                dfs(i);  
      
    dfs(1);  
    

In order to simplify the test results checking procedure, Dmitry Olegovich decided to create a tree T such that the result is his favorite sequence b. On the other hand, Dmitry Olegovich doesn't want to provide students with same trees as input, otherwise they might cheat. That's why Dmitry Olegovich is trying to find out the number of different trees T such that the result of running the above pseudocode with T as input is exactly the sequence b. Can you help him?

Two trees with n vertices are called different if their adjacency matrices a1 and a2 are different, i. e. there exists a pair (i, j), such that 1 ≤ i, j ≤ n and a1[i][j] ≠ a2[i][j].

Input

The first line contains the positive integer n (1 ≤ n ≤ 500) — the length of sequence b. 

The second line contains n positive integers b1, b2, ..., bn (1 ≤ bi ≤ n). It is guaranteed that b is a permutation, or in other words, each of the numbers 1, 2, ..., n appears exactly once in the sequence b. Also it is guaranteed that b1 = 1.

Output

Output the number of trees satisfying the conditions above modulo 109 + 7.

Examples

Input

3
1 2 3


Output

2


Input

3
1 3 2


Output

1
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;


import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.NavigableSet;
import java.util.Random;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeSet;



public final class CF_ProgressMonitoring_v2 {

	void log(int[] X){
		int L=X.length;
		for (int i=0;i<L;i++){
			logWln(X[i]+" ");
		}
		log("");
	}


	void log(long[] X){
		int L=X.length;
		for (int i=0;i<L;i++){
			logWln(X[i]+" ");
		}
		log("");
	}
	void log(Object[] X){
		int L=X.length;
		for (int i=0;i<L;i++){
			logWln(X[i]+" ");
		}
		log("");
	}


	void log(Object o){
		logWln(o+"\n");
	}

	void logWln(Object o){
		System.out.print(o);
		//outputWln(o);

	}
	void info(Object o){
		System.out.println(o);
		//output(o);
	}

	void output(Object o){

		outputWln(""+o+"\n");

	}

	void outputWln(Object o){
		// System.out.print(o);

		try {
			out.write(""+ o);
		} catch (Exception e) {

		}
	}


	String next(){
		while (st== null|| !st.hasMoreTokens()) {
			try {
				st=new StringTokenizer(in.readLine());
			} catch (Exception e) {
			}
		}
		return st.nextToken();
	}

	String nextLine(){
		try {
			return in.readLine();
		} catch (Exception e) {
		}
		return null;
	}

	int nextInt(){
		return Integer.parseInt(next());
	}


	long nextLong(){
		return Long.parseLong(next());


	}


	int[] used;
	int[][] a;
	int N;
	int[] b;

	void dfs(int v){
		log(v);
		used[v] = 1;
		for (int i=0;i<N;i++){
			if (a[v][i] == 1 && used[i] == 0)
				dfs(i);
		}
	}
	
	
	long[][] cacheH;
	long[][] cacheV;
	
	
	long computeHorizontal(String s,int l,int r){
		// on commence à l
		// on va jusqu'à r
		// on segment en vertical ou horizontal
		// mais pour segmenter en horizontal il ne faut pas être inférieur à b[l]
		
		log(s+" l:"+l+" r:"+r);
		
		long res=0;
		if (r<l) {
			log(s+" "+0);
			return 0;
		}
		if (cacheH[l][r]>0) 
			return cacheH[l][r]-1;
		if (r==l) {
			log(s+" "+1);
			return 1;
		}
		if (r==l+1){
			if (b[r]>b[l])
				res=2;
			else
				res=1;
			cacheH[l][r]=res+1;
			log(s+" "+res);
			return res;
		}
		
	
		long t1=0,t2=0;
		
		for (int x=l+1;x<=r;x++){
			if (b[x]>b[l]){
				if (x==l+1)
					t1=1;
				else
					t1=computeHorizontal(s+"-",l+1,x-1);
				t2=computeHorizontal(s+"-",x,r);
				res+=t1*t2;
			}
		}
		res+=computeHorizontal(s+"-",l+1,r);
		cacheH[l][r]=res+1;
		log(s+" "+res);
		return res;
	}

	
	
	long computeHorizontal(int l,int r){
		// on commence à l
		// on va jusqu'à r
		// on segment en vertical ou horizontal
		// mais pour segmenter en horizontal il ne faut pas être inférieur à b[l]
		
		long res=0;
		if (r<l) {
			return 0;
		}
		if (cacheH[l][r]>0) 
			return cacheH[l][r]-1;
		if (r==l) {
			cacheH[l][r]=1+1;
			return 1;
		}
		if (r==l+1){
			if (b[r]>b[l])
				res=2;
			else
				res=1;
			cacheH[l][r]=res+1;
			return res;
		}
		
	
		long t1=0,t2=0;
		
		for (int x=l+1;x<=r;x++){
			if (b[x]>b[l]){
				if (x==l+1)
					t1=1;
				else
					t1=computeHorizontal(l+1,x-1);
				t2=computeHorizontal(x,r);
				long v=t1*t2;
				if (v>=MOD)
					v%=MOD;
				res+=v;
				if (res>=MOD)
					res%=MOD;
			}
		}
		res+=computeHorizontal(l+1,r);
		if (res>=MOD)
			res%=MOD;
		cacheH[l][r]=res+1;
		return res;
	}
	
	void solve(){
		cacheH=new long[N+1][N+1];
		if (N==1)
			output("1");
		else
			output(computeHorizontal(1,N-1));
	}
	



	// Global vars
	StringTokenizer st;
	BufferedReader in;
	BufferedWriter out;
	static long MOD=1000000007;

	void process() throws Exception {



		Locale.setDefault(Locale.US);

		out = new BufferedWriter(new OutputStreamWriter(System.out));
		in=new BufferedReader(new InputStreamReader(System.in));

		N=nextInt();
		b=new int[N];
		for (int i=0;i<N;i++)
			b[i]=nextInt()-1;

		solve();
		try {
			out.close();
		}
		catch (Exception e){}


	}



	public static void main(String[] args) throws Exception {
		CF_ProgressMonitoring_v2 J=new CF_ProgressMonitoring_v2();

		J.process();


	}


}

