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>
#include <bits/stdc++.h>
using namespace std;
int TurnWhere(const pair<long long, long long>& p1,
              const pair<long long, long long>& p2,
              const pair<long long, long long>& p3) {
  long long val = (p2.second - p1.second) * (p3.first - p2.first) -
                  (p2.first - p1.first) * (p3.second - p2.second);
  if (val == 0LL) return 0LL;
  if (val > 0LL)
    return 1LL;
  else
    return 2LL;
}
bool IsCollinear(const pair<long long, long long>& p1,
                 const pair<long long, long long>& p2,
                 const pair<long long, long long>& p3) {
  return TurnWhere(p1, p2, p3) == 0LL;
}
bool SegmentContainsPoint(const pair<pair<long long, long long>,
                                     pair<long long, long long> >& segment,
                          const pair<long long, long long>& point) {
  if (point == segment.first || point == segment.second) return true;
  if (!IsCollinear(segment.first, segment.second, point)) {
    return false;
  }
  return (point.first >= min(segment.first.first, segment.second.first) &&
          point.first <= max(segment.first.first, segment.second.first) &&
          point.second >= min(segment.first.second, segment.second.second) &&
          point.second <= max(segment.first.second, segment.second.second));
}
bool IsTouchingOrIntersecting(
    const pair<pair<long long, long long>, pair<long long, long long> >& s1,
    const pair<pair<long long, long long>, pair<long long, long long> >& s2) {
  int o1x = TurnWhere(s1.first, s1.second, s2.first);
  int o1y = TurnWhere(s1.first, s1.second, s2.second);
  int o2x = TurnWhere(s2.first, s2.second, s1.first);
  int o2y = TurnWhere(s2.first, s2.second, s1.second);
  if (o1x != o1y && o2x != o2y) {
    return true;
  }
  if ((!o1x && SegmentContainsPoint(s1, s2.first)) ||
      (!o1y && SegmentContainsPoint(s1, s2.second)) ||
      (!o2x && SegmentContainsPoint(s2, s1.first)) ||
      (!o2y && SegmentContainsPoint(s2, s1.second))) {
    return true;
  }
  return false;
}
pair<long long, long long> PointToVector(const pair<long long, long long>& p1,
                                         const pair<long long, long long>& p2) {
  return make_pair(p2.first - p1.first, p2.second - p1.second);
}
long long PolygonArea(const vector<pair<long long, long long> >& poly) {
  int n = ((int)(poly).size());
  long long area = 0LL;
  for (int i = 0; i < n; ++i) {
    area += poly[i].first * poly[(i + 1) % n].second;
    area -= poly[i].second * poly[(i + 1) % n].first;
  }
  return area / 2LL;
}
int PointInsidePolygon(const vector<pair<long long, long long> >& poly,
                       const pair<long long, long long>& p) {
  int n = ((int)(poly).size());
  int penetrations = 0;
  for (int i = 0; i < n; ++i) {
    if (poly[i].second == p.second) {
      if (poly[i].first > p.first) {
        if (poly[(i - 1 + n) % n].second == p.second) {
          continue;
        }
        int j = i;
        while (poly[(j + 1) % n].second == p.second) {
          j = (j + 1) % n;
        }
        if (TurnWhere(p, poly[i], poly[(i - 1 + n) % n]) !=
            TurnWhere(p, poly[i], poly[(j + 1) % n])) {
          penetrations += 1;
        }
      }
    } else if (poly[(i + 1) % n].second != p.second) {
      if (IsTouchingOrIntersecting(
              {poly[i], poly[(i + 1) % n]},
              {p,
               {max(max(poly[i].first, poly[(i + 1) % n].first), p.first),
                p.second}})) {
        penetrations += 1;
      }
    }
  }
  return penetrations % 2;
}
long long x[400];
long long y[400];
long long dbx[400];
long long dby[400];
int isok[400][400];
long long modu = 1000000007LL;
long long dp[210][210];
int n;
long long Solve(int fr, int bk) {
  long long& alias = dp[fr][bk];
  if (fr != bk && (bk - fr + n) % n < 3) return alias = 1LL;
  if (alias != -1LL) return alias;
  alias = 0LL;
  if (isok[(fr + 1) % n][bk]) {
    alias = Solve((fr + 1) % n, bk);
  }
  for (int i = (bk - 1 + n) % n; i != fr; i = (i - 1 + n) % n) {
    if (i == (fr + 1) % n) break;
    if (!isok[fr][i]) continue;
    if (bk != (i + 1) % n && !isok[i][bk]) continue;
    (alias += ((Solve(i, bk) * Solve(fr, i)) % modu)) %= modu;
  }
  return alias;
}
int main() {
  for (int(i) = 0; (i) < (210); ++(i))
    for (int(j) = 0; (j) < (210); ++(j)) dp[i][j] = -1LL;
  cin >> n;
  int b = 0;
  for (int(i) = 0; (i) < (n); ++(i)) {
    cin >> x[i] >> y[i];
    x[i] *= 2;
    y[i] *= 2;
    dbx[i] = x[i];
    dby[i] = y[i];
  }
  if (n == 200 && x[0] == 542 * 2) {
    b = 1;
  }
  if (n == 3) {
    cout << 1 << endl;
    return 0;
  }
  vector<pair<long long, long long> > polygon;
  for (int(i) = 0; (i) < (n); ++(i)) {
    polygon.push_back({dbx[i], dby[i]});
  }
  for (int(i) = 0; (i) < (n); ++(i))
    for (int(j) = 0; (j) < (n); ++(j))
      if (i != j) {
        if (i == (j + 1) % n || j == (i + 1) % n) continue;
        isok[i][j] = 1;
        for (int(k) = 0; (k) < (n); ++(k)) {
          int l = (k + 1) % n;
          if (i != k && i != l && j != k && j != l) {
            if (IsTouchingOrIntersecting(
                    {{dbx[i], dby[i]}, {dbx[j], dby[j]}},
                    {{dbx[k], dby[k]}, {dbx[l], dby[l]}})) {
              isok[i][j] = 0;
              break;
            }
          }
          if (k != i && k != j) {
            if (SegmentContainsPoint({{dbx[i], dby[i]}, {dbx[j], dby[j]}},
                                     {dbx[k], dby[k]})) {
              isok[i][j] = 0;
              break;
            }
          }
        }
        if (!PointInsidePolygon(
                polygon, {(dbx[i] + dbx[j]) / 2LL, (dby[i] + dby[j]) / 2LL})) {
          isok[i][j] = 0;
        }
      }
  cout << Solve(0, n - 1) << endl;
}
