This time our child has a simple polygon. He has to find the number of ways to split the polygon into non-degenerate triangles, each way must satisfy the following requirements:

  * each vertex of each triangle is one of the polygon vertex; 
  * each side of the polygon must be the side of exactly one triangle; 
  * the area of intersection of every two triangles equals to zero, and the sum of all areas of triangles equals to the area of the polygon; 
  * each triangle must be completely inside the polygon; 
  * each side of each triangle must contain exactly two vertices of the polygon. 



The picture below depicts an example of a correct splitting.

<image>

Please, help the child. Calculate the described number of ways modulo 1000000007 (109 + 7) for him.

Input

The first line contains one integer n (3 ≤ n ≤ 200) — the number of vertices of the polygon. Then follow n lines, each line containing two integers. The i-th line contains xi, yi (|xi|, |yi| ≤ 107) — the i-th vertex of the polygon in clockwise or counterclockwise order.

It's guaranteed that the polygon is simple.

Output

Output the number of ways modulo 1000000007 (109 + 7).

Examples

Input

4
0 0
0 1
1 1
1 0


Output

2


Input

4
0 0
1 0
0 1
-1 0


Output

1


Input

5
0 0
1 0
1 1
0 1
-2 -1


Output

3

Note

In the first sample, there are two possible splittings:

<image>

In the second sample, there are only one possible splitting:

<image>

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

import static java.util.Arrays.*;

public class C {
	private static final int mod = (int)1e9+7;

	final Random random = new Random(0);
	final IOFast io = new IOFast();

	/// MAIN CODE
	public void run() throws IOException {
//		int TEST_CASE = Integer.parseInt(new String(io.nextLine()).trim());
		int TEST_CASE = 1;
		while(TEST_CASE-- != 0) {
			int n = io.nextInt();
			int m = n;
			Point[] p = new Point[n];
			int[][] pt = new int[n][2];
			
			for(int i = 0; i < n; i++) {
				pt[i][0] = io.nextInt();
				pt[i][1] = io.nextInt();
				p[i] = new Point(pt[i][0], pt[i][1]);
			}
			
			Polygon poly = new Polygon(p);
			

			boolean[][] g = new boolean[n][n];
			for(int i = 0; i < n; i++) {
				for(int j = i + 1; j < n; j++) {
					g[j][i] = g[i][j] = poly.canConnectVertexThroughInsidePolygon(i, j);
//					System.err.println(i + " " + j + " " + g[i][j]);
				}
			}
			
			long[][] dp = new long[n][n];
			for(int i = 0; i < n; i++) {
				dp[i][i] = 1;
				if(i < n - 1) dp[i][i+1] = 1;
			}
			
			for(int k = 3; k <= n; k++) {
				for(int i = 0; i + k <= n; i++) {
					final int j = i + k - 1;
					if(!g[i][j]) continue;
					for(int l = i + 1; l < j; l++) if(g[i][l] && g[l][j]) {
						dp[i][j] += dp[i][l] * dp[l][j] % mod;
						dp[i][j] %= mod;
					}
				}
			}
			
			io.out.println(dp[0][n-1] % mod);
		}
	}
	
	
	static
	public class Polygon {
		private static final double eps = 1e-9;
		
		int n;
		Point[] ps;
		
		public Polygon(Point[] ps) {
			this.ps = ps;
			this.n = ps.length;
		}

		/*
		static int ccw(Point a, Point b, Point c) {
			b=b.sub(a); c=c.sub(a);
			if (cross(b, c) > 0)   return +1;		// counter clockwise
			if (cross(b, c) < 0)   return -1;		// clockwise
			if (dot(b, c) < 0)     return +2;		// c--a--b on line
			if (b.norm() < c.norm()) return -2;		// a--b--c on line
			return 0;								// a--c--b on line
		}
		*/
		// pt inside polygon
		public boolean inside(Point pt) {
			final boolean onEdge = true;
			
			boolean in = false;
			Point left = new Point(1e10, 0).rotate(1);
			for(int i = 0; i < n; i++) {
				Point a = ps[i];
				Point b = ps[(i+1)%n];
				
				final int ccw = Point.ccw(a, b, pt);
				if(ccw == 0) {
					return onEdge;
				}
				/*
				else if(ccw == 2 || ccw == -2) {
					continue;
//					return onEdge;
				}*/
				
				if(Point.intersectSS(a, b, pt, left)) {
					in ^= true;
				}
			}
			return in;
		}
		
		// 
		public boolean canConnectVertexThroughInsidePolygon(int i, int j) {
			if(Math.abs(j - i) == 1 || Math.abs(j - i) == n - 1) {
				return true;
			}
			
			if(!inside(ps[i].add(ps[j]).div(2))) {
				return false;
			}

			/*
			static int ccw(Point a, Point b, Point c) {
				b=b.sub(a); c=c.sub(a);
				if (cross(b, c) > 0)   return +1;		// counter clockwise
				if (cross(b, c) < 0)   return -1;		// clockwise
				if (dot(b, c) < 0)     return +2;		// c--a--b on line
				if (b.norm() < c.norm()) return -2;		// a--b--c on line
				return 0;								// a--c--b on line
			}
			*/
			
			for(int k = -1; k <= 1; k += 2) {
				final int l1 = (i + k + n) % n;
				final int l2 = (j + k + n) % n;
				if(Point.ccw(ps[i], ps[l1], ps[j]) == -2) return false;
				if(Point.ccw(ps[j], ps[l2], ps[i]) == -2) return false;
			}
			
			for(int k = 0; k < n; k++) {
				final int l = (k + 1) % n;
				if(i == k || i == l || j == k || j == l) continue;
				Point a = ps[i];
				Point b = ps[j];
				Point c = ps[k];
				Point d = ps[l];
				if(Point.intersectSS(a, b, c, d)) {
					return false;
				}
			}
			
			return true;
		}
	}
	
	
	static
	public class Point implements Comparable<Point> {
		public double x, y;
		public Point() { }
		public Point(double xx, double yy) { x = xx; y = yy; }
		public Point(Point p) { this(p.x, p.y); }
		public Point rotate(final double theta) {
			final double a = x, b = y;
			x = a * Math.cos(theta) - b * Math.sin(theta);
			y = a * Math.sin(theta) + b * Math.cos(theta);
			return this;
		}
		public Point addM(Point p) { return addM(p.x, p.y); }
		public Point addM(double x, double y) {
			this.x += x;
			this.y += y;
			return this;
		}
		public Point add(Point p) { return add(p.x, p.y); }
		public Point add(double x, double y) {
			return new Point(this).addM(x, y);
		}
		public Point subM(Point p) { return subM(p.x, p.y); }
		public Point subM(double x, double y) {
			this.x -= x;
			this.y -= y;
			return this;
		}
		public Point sub(Point p) { return sub(p.x, p.y); }
		public Point sub(double x, double y) {
			return new Point(this).subM(x, y);
		}
		public Point mulM(double d) {
			x *= d;
			y *= d;
			return this;
		}
		public Point mul(double d) {
			return new Point(this).mulM(d);
		}
		public Point divM(double v) {
			this.x /= v;
			this.y /= v;
			return this;
		}
		public Point div(double v) {
			return new Point(this).divM(v);
		}

		public static double dist(Point a, Point b) { return a.sub(b).abs(); }
		public static double cross(Point a, Point b) { return a.x*b.y - a.y*b.x; }
		public static double dot(Point a, Point b) { return a.x*b.x + a.y*b.y; }
		public double dot(Point p) { return dot(this, p); }

		public double norm() { return x*x+y*y; }
		public double abs() { return Math.sqrt(norm()); }

		// spaghetti source
		// http://www.prefield.com/algorithm/geometry/ccw.html
		static int ccw(Point a, Point b, Point c) {
			b=b.sub(a); c=c.sub(a);
			if (cross(b, c) > 0)   return +1;       // counter clockwise
			if (cross(b, c) < 0)   return -1;       // clockwise
			if (dot(b, c) < 0)     return +2;       // c--a--b on line
			if (b.norm() < c.norm()) return -2;       // a--b--c on line
			return 0;
		}

		// spaghetti source
		static boolean intersectSS(Point[] p, Point[] q) {
			return ccw(p[0], p[1], q[0]) * ccw(p[0], p[1], q[1]) <= 0 &&
					ccw(q[0], q[1], p[0]) * ccw(q[0], q[1], p[1]) <= 0;
		}

		static boolean intersectSS(Point p1, Point p2, Point q1, Point q2) {
			return ccw(p1, p2, q1) * ccw(p1, p2, q2) <= 0 &&
					ccw(q1, q2, p1) * ccw(q1, q2, p2) <= 0;
		}
		
		public String toString() {
			return "(" + x + "," + y + ")";
		}
		
		@Override
		public int compareTo(Point o) {
			final int cmp = Double.compare(x, o.x);
			return cmp != 0 ? cmp : Double.compare(y, o.y);
		}
		
		public Point copy() {
			return new Point(this);
		}
	}
	
	static
	public class Segment {
		private static final double eps = 1e-9;
		
		public Point s, t;
		
		public Segment(Point a, Point b) { s = a; t = b; }
		public Segment() { }
		
		public double cross(Point p) {
			final double x1 = p.x - s.x, y1 = p.y - s.y;
			final double x2 = t.x - s.x, y2 = t.y - s.y;
			return x1 * y2 - x2 * y1;
		}
		
		public boolean intersect(Segment seg) {
			final double z11 = Math.signum(cross(seg.s)), z12 = Math.signum(cross(seg.t));
			final double z21 = Math.signum(seg.cross(s)), z22 = Math.signum(seg.cross(t));
			return z11 * z12 <= 0 && z21 * z22 <= 0;
		}
		
		public Point projection(Point p) {
			final Point d = s.sub(t);
			final double t = p.sub(s).dot(d) / d.norm();
			return d.mulM(t).addM(s);
		}
		
		public static Point projection(Point s, Point t, Point p) {
			final Point d = s.sub(t);
			final double tt = p.sub(s).dot(d) / d.norm();
			return d.mulM(tt).addM(s);
		}
		
		public double dist(Segment seg) {
			if(intersect(seg)) return 0;
			return Math.min(
					Math.min(dist(seg.s), dist(seg.t)),
					Math.min(seg.dist(s), seg.dist(t)));
		}
		
		boolean intersect(Point p) {
			return s.sub(p).abs() + t.sub(p).abs() - t.sub(s).abs() < eps;
		}
		
		public double dist(final Point pt) {
			final Point p = projection(pt);
			if(intersect(p)) return p.subM(pt).abs();
			return Math.min(s.sub(pt).abs(), t.sub(pt).abs());
		}
		
		void set(final Point s, final Point t) {
			this.s = s;
			this.t = t;
		}
		
		public String toString() {
			return "[" + s + ";" + t + "]";
		}
	}


	/*
	static
	public class Point implements Comparable<Point> {
		public long x, y;
		public Point() { }
		public Point(long xx, long yy) { x = xx; y = yy; }
		public Point(Point p) { this(p.x, p.y); }
//		public Point rotate(final double theta) {
//			final double a = x, b = y;
//			x = a * Math.cos(theta) - b * Math.sin(theta);
//			y = a * Math.sin(theta) + b * Math.cos(theta);
//			return this;
//		}
		public Point addM(Point p) { return addM(p.x, p.y); }
		public Point addM(long x, long y) {
			this.x += x;
			this.y += y;
			return this;
		}
		public Point add(Point p) { return add(p.x, p.y); }
		public Point add(long x, long y) {
			return new Point(this).addM(x, y);
		}
		public Point subM(Point p) { return subM(p.x, p.y); }
		public Point subM(long x, long y) {
			this.x -= x;
			this.y -= y;
			return this;
		}
		public Point sub(Point p) { return sub(p.x, p.y); }
		public Point sub(long x, long y) {
			return new Point(this).subM(x, y);
		}
		public Point mulM(long d) {
			x *= d;
			y *= d;
			return this;
		}
		public Point mul(long d) {
			return new Point(this).mulM(d);
		}
		public Point divM(long v) {
			this.x /= v;
			this.y /= v;
			return this;
		}
		public Point div(long v) {
			return new Point(this).divM(v);
		}

		public static double dist(Point a, Point b) { return a.sub(b).abs(); }
		public static long cross(Point a, Point b) { return a.x*b.y - a.y*b.x; }
		public static long dot(Point a, Point b) { return a.x*b.x + a.y*b.y; }
		public long dot(Point p) { return dot(this, p); }

		public long norm() { return x*x+y*y; }
		public double abs() { return Math.sqrt(norm()); }

		// spaghetti source
		// http://www.prefield.com/algorithm/geometry/ccw.html
		// @todo eps
		static int ccw(Point a, Point b, Point c) {
			b=b.sub(a); c=c.sub(a);
			if (cross(b, c) > 0)   return +1;       // counter clockwise
			if (cross(b, c) < 0)   return -1;       // clockwise
			if (dot(b, c) < 0)     return +2;       // c--a--b on line
			if (b.norm() < c.norm()) return -2;       // a--b--c on line
			return 0;
		}

		// spaghetti source
		static boolean intersectSS(Point[] p, Point[] q) {
			return ccw(p[0], p[1], q[0]) * ccw(p[0], p[1], q[1]) <= 0 &&
					ccw(q[0], q[1], p[0]) * ccw(q[0], q[1], p[1]) <= 0;
		}

		static boolean intersectSS(Point p1, Point p2, Point q1, Point q2) {
//			return ccw(p1, p2, q1) * ccw(p1, p2, q2) < 0 &&
//					ccw(q1, q2, p1) * ccw(q1, q2, p2) < 0;
			return ccw(p1, p2, q1) * ccw(p1, p2, q2) <= 0 &&
					ccw(q1, q2, p1) * ccw(q1, q2, p2) <= 0;
		}
		
		public String toString() {
			return "(" + x + "," + y + ")";
		}
		
		@Override
		public int compareTo(Point o) {
			final int cmp = Long.compare(x, o.x);
			return cmp != 0 ? cmp : Long.compare(y, o.y);
		}
		
		public Point copy() {
			return new Point(this);
		}
	}
	*/

	/// TEMPLATE
	static int gcd(int n, int r) { return r == 0 ? n : gcd(r, n%r); }
	static long gcd(long n, long r) { return r == 0 ? n : gcd(r, n%r); }
	
	static <T> void swap(T[] x, int i, int j) {
		T t = x[i];
		x[i] = x[j];
		x[j] = t;
	}
	
	static void swap(int[] x, int i, int j) {
		int t = x[i];
		x[i] = x[j];
		x[j] = t;
	}
	

	static void radixSort(int[] xs) {
		int[] cnt = new int[(1<<16)+1];
		int[] ys = new int[xs.length];
		
		for(int j = 0; j <= 16; j += 16) {
			Arrays.fill(cnt, 0);
			for(int x : xs) { cnt[(x>>j&0xFFFF)+1]++; }
			for(int i = 1; i < cnt.length; i++) { cnt[i] += cnt[i-1]; }
			for(int x : xs) { ys[cnt[x>>j&0xFFFF]++] = x; }
			{ final int[] t = xs; xs = ys; ys = t; }
		}
	}
	
	static void radixSort(long[] xs) {
		int[] cnt = new int[(1<<16)+1];
		long[] ys = new long[xs.length];
		
		for(int j = 0; j <= 48; j += 16) {
			Arrays.fill(cnt, 0);
			for(long x : xs) { cnt[(int)(x>>j&0xFFFF)+1]++; }
			for(int i = 1; i < cnt.length; i++) { cnt[i] += cnt[i-1]; }
			for(long x : xs) { ys[cnt[(int)(x>>j&0xFFFF)]++] = x; }
			{ final long[] t = xs; xs = ys; ys = t; }
		}
	}
	

	static void arrayIntSort(int[][] x, int... keys) {
		Arrays.sort(x, new ArrayIntsComparator(keys));
	}
	
	static class ArrayIntsComparator implements Comparator<int[]> {
		final int[] KEY;
		
		public ArrayIntsComparator(int... key) {
			KEY = key;
		}
		
		@Override
		public int compare(int[] o1, int[] o2) {
			for(int k : KEY) if(o1[k] != o2[k]) return o1[k] - o2[k];
			return 0;
		}
	}
	
	static class ArrayIntComparator implements Comparator<int[]> {
		final int KEY;
		
		public ArrayIntComparator(int key) {
			KEY = key;
		}
		
		@Override
		public int compare(int[] o1, int[] o2) {
			return o1[KEY] - o2[KEY];
		}
	}
	
	
	void main() throws IOException {
		//		IOFast.setFileIO("rle-size.in", "rle-size.out");
		try {
			run();
		}
		catch (EndOfFileRuntimeException e) { }
		io.out.flush();
	}

	public static void main(String[] args) throws IOException {
		new C().main();
	}
	
	static class EndOfFileRuntimeException extends RuntimeException {
		private static final long serialVersionUID = -8565341110209207657L; }

	static
	public class IOFast {
		private BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		private PrintWriter out = new PrintWriter(System.out);

		void setFileIO(String ins, String outs) throws IOException {
			out.flush();
			out.close();
			in.close();
			in = new BufferedReader(new FileReader(ins));
			out = new PrintWriter(new FileWriter(outs));
			System.err.println("reading from " + ins);
		}

		//		private static final int BUFFER_SIZE = 50 * 200000;
		private static int pos, readLen;
		private static final char[] buffer = new char[1024 * 8];
		private static char[] str = new char[500*8*2];
		private static boolean[] isDigit = new boolean[256];
		private static boolean[] isSpace = new boolean[256];
		private static boolean[] isLineSep = new boolean[256];

		static {
			for(int i = 0; i < 10; i++) { isDigit['0' + i] = true; }
			isDigit['-'] = true;
			isSpace[' '] = isSpace['\r'] = isSpace['\n'] = isSpace['\t'] = true;
			isLineSep['\r'] = isLineSep['\n'] = true;
		}

		public int read() throws IOException {
			if(pos >= readLen) {
				pos = 0;
				readLen = in.read(buffer);
				if(readLen <= 0) { throw new EndOfFileRuntimeException(); }
			}
			return buffer[pos++];
		}

		public int nextInt() throws IOException {
			int len = 0;
			str[len++] = nextChar();
			len = reads(len, isSpace);
			
			int i = 0;
			int ret = 0;
			if(str[0] == '-') { i = 1; }
			for(; i < len; i++) ret = ret * 10 + str[i] - '0';
			if(str[0] == '-') { ret = -ret; }
			return ret;
//			return Integer.parseInt(nextString());
		}

		public long nextLong() throws IOException {
			int len = 0;
			str[len++] = nextChar();
			len = reads(len, isSpace);
			
			int i = 0;
			long ret = 0;
			if(str[0] == '-') { i = 1; }
			for(; i < len; i++) ret = ret * 10 + str[i] - '0';
			if(str[0] == '-') { ret = -ret; }
			return ret;
//			return Long.parseLong(nextString());
		}

		public char nextChar() throws IOException {
			while(true) {
				final int c = read();
				if(!isSpace[c]) { return (char)c; }
			}
		}
		
		int reads(int len, boolean[] accept) throws IOException {
			try {
				while(true) {
					final int c = read();
					if(accept[c]) { break; }
					
					if(str.length == len) {
						char[] rep = new char[str.length * 3 / 2];
						System.arraycopy(str, 0, rep, 0, str.length);
						str = rep;
					}
					
					str[len++] = (char)c;
				}
			}
			catch(EndOfFileRuntimeException e) { ; }
			
			return len;
		}
		
		int reads(char[] cs, int len, boolean[] accept) throws IOException {
			try {
				while(true) {
					final int c = read();
					if(accept[c]) { break; }
					cs[len++] = (char)c;
				}
			}
			catch(EndOfFileRuntimeException e) { ; }
			
			return len;
		}

		public char[] nextLine() throws IOException {
			int len = 0;
//			str[len++] = nextChar();
			str[len++] = (char)read();
			len = reads(len, isLineSep);
			
			try {
				if(str[len-1] == '\r') { len--; read(); }
			}
			catch(EndOfFileRuntimeException e) { ; }
			
			return Arrays.copyOf(str, len);
		}

		public String nextString() throws IOException {
			return new String(next());
		}

		public char[] next() throws IOException {
			int len = 0;
			str[len++] = nextChar();
			len = reads(len, isSpace);
			return Arrays.copyOf(str, len);
		}

		public int next(char[] cs) throws IOException {
			int len = 0;
			cs[len++] = nextChar();
			len = reads(cs, len, isSpace);
			return len;
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(nextString());
		}

		public long[] nextLongArray(final int n) throws IOException {
			final long[] res = new long[n];
			for(int i = 0; i < n; i++) {
				res[i] = nextLong();
			}
			return res;
		}

		public int[] nextIntArray(final int n) throws IOException {
			final int[] res = new int[n];
			for(int i = 0; i < n; i++) {
				res[i] = nextInt();
			}
			return res;
		}

		public int[][] nextIntArray2D(final int n, final int k) throws IOException {
			final int[][] res = new int[n][];
			for(int i = 0; i < n; i++) {
				res[i] = nextIntArray(k);
			}
			return res;
		}

		public int[][] nextIntArray2DWithIndex(final int n, final int k) throws IOException {
			final int[][] res = new int[n][k+1];
			for(int i = 0; i < n; i++) {
				for(int j = 0; j < k; j++) {
					res[i][j] = nextInt();
				}
				res[i][k] = i;
			}
			return res;
		}

		public double[] nextDoubleArray(final int n) throws IOException {
			final double[] res = new double[n];
			for(int i = 0; i < n; i++) {
				res[i] = nextDouble();
			}
			return res;
		}

	}

}
