#include <algorithm>#include <bitset>#include <cctype>#include <climits>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <functional>#include <iomanip>#include <iostream>#include <list>#include <map>#include <numeric>#include <queue>#include <set>#include <sstream>#include <stack>#include <string>#include <typeinfo>#include <utility>#include <vector>using namespace std;typedef long long LL;typedef vector<int> VI;typedef vector<long long> VL;typedef vector<double> VD;typedef vector<string> VS;const double eps = 1e-8;const double pi = acos(-1.0);int sgn(double d) { return d > eps ? 1 : (d < -eps ? -1 : 0);}double trim(double d, double l = 1.0) { return d > l ? l : (d < -l ? -l : d);}struct point { double x, y; point(double _x = 0, double _y = 0): x(_x), y(_y) { } void input() { scanf("%lf%lf", &x, &y); } double len() const { return sqrt(x * x + y * y); } point trunc(double l) const { double r = l / len(); return point(x * r, y * r); } point rotate_left() const { return point(-y, x); } point rotate_left(double ang) const { double c = cos(ang), s = sin(ang); return point(x * c - y * s, y * c + x * s); } point rotate_right() const { return point(y, -x); } point rotate_right(double ang) const { double c = cos(ang), s = sin(ang); return point(x * c + y * s, y * c - x * s); }};bool operator==(const point& p1, const point& p2) { return sgn(p1.x - p2.x) == 0 && sgn(p1.y - p2.y) == 0;}bool operator!=(const point& p1, const point& p2) { return !(p1 == p2);}bool operator<(const point& p1, const point& p2) { return sgn(p1.x - p2.x) == 0 ? sgn(p1.y - p2.y) < 0 : p1.x < p2.x;}bool operator>(const point& p1, const point& p2) { return sgn(p1.x - p2.x) == 0 ? sgn(p1.y - p2.y) > 0 : p1.x > p2.x;}point operator+(const point& p1, const point& p2) { return point(p1.x + p2.x, p1.y + p2.y);}point operator-(const point& p1, const point& p2) { return point(p1.x - p2.x, p1.y - p2.y);}double operator^(const point& p1, const point& p2) { return p1.x * p2.x + p1.y * p2.y;}double operator*(const point& p1, const point& p2) { return p1.x * p2.y - p1.y * p2.x;}point operator*(const point& p, double r) { return point(p.x * r, p.y * r);}point operator/(const point& p, double r) { return point(p.x / r, p.y / r);}const int base = 10000;const int cap = 64;struct xnum { int len; vector<int> data; xnum() : len(0) {} xnum(const xnum& v) : len(v.len) { data = v.data; } xnum(int v) : len(0) { for (; v > 0; v /= base) data.push_back(v % base); len = data.size(); } xnum& operator=(const xnum& v) { len = v.len; data = v.data; return *this; } int& operator[](int index) { if (index >= data.size()) data.resize(index + 1); return data[index]; } int operator[](int index) const { return data[index]; } }; int compare(const xnum& a, const xnum& b) { int i; if (a.len != b.len) return a.len > b.len ? 1 : -1; for (i = a.len - 1; i >= 0 && a[i] == b[i]; i--); if (i < 0) return 0; return a[i] > b[i] ? 1 : -1; } xnum operator+(const xnum& a, const xnum& b) { xnum r; int i, c = 0; for (i = 0; i < a.len || i < b.len || c > 0; i++) { if (i < a.len) c += a[i]; if (i < b.len) c += b[i]; r[i] = c % base; c /= base; } r.len = i; return r; } xnum operator-(const xnum& a, const xnum& b) { xnum r; int c = 0; r.len = a.len; for (int i = 0; i < r.len; i++) { r[i] = a[i] - c; if (i < b.len) r[i] -= b[i]; if (r[i] < 0) c = 1, r[i] += base; else c = 0; } while (r.len > 0 && r[r.len - 1] == 0) r.len--; return r; }xnum operator*(const xnum& a, const int b) { int i; if (b == 0) return 0; xnum r; int c = 0; for (i = 0; i < a.len || c > 0; i++) { if (i < a.len) c += a[i] * b; r[i] = c % base; c /= base; } r.len = i; return r; } xnum operator*(const xnum& a, const xnum& b) { if (b.len == 0) return 0; xnum r; for (int i = 0; i < a.len; i++) { int c = 0; for (int j = 0; j < b.len || c > 0; j++) { if (j < b.len) c += a[i] * b[j]; if (i + j < r.len) c += r[i + j]; if (i + j >= r.len) r[r.len++] = c % base; else r[i + j] = c % base; c /= base; } } return r; } xnum operator/(const xnum& a, const int b) { xnum r; int c = 0; for (int i = a.len - 1; i >= 0; i--) { c = c * base + a[i]; r[i] = c / b; c %= b; } r.len = a.len; while (r.len > 0 && r[r.len - 1] == 0) r.len--; return r; } xnum operator/(const xnum& a, const xnum& b) { xnum r, c = 0; int left, right, mid; for (int i = a.len - 1; i >= 0; i--) { c = c * base + a[i]; left = 0; right = base - 1; while (left < right) { mid = (left + right + 1) / 2; if (compare(b * mid, c) <= 0) left = mid; else right = mid - 1; } r[i] = left; c = c - b * left; } r.len = a.len; while (r.len > 0 && r[r.len - 1] == 0) r.len--; return r; } xnum operator%(const xnum& a, const xnum& b) { xnum r, c = 0; int left, right, mid; for (int i = a.len - 1; i >= 0; i--) { c = c * base + a[i]; left = 0; right = base - 1; while (left < right) { mid = (left + right + 1) / 2; if (compare(b * mid, c) <= 0) left = mid; else right = mid - 1; } r[i] = left; c = c - b * left; } r.len = a.len; while (r.len > 0 && r[r.len - 1] == 0) r.len--; return c; } istream& operator>>(istream& in, xnum& v) { char ch; for (v = 0; in >> ch;) { v = v * 10 + (ch - '0'); if (cin.peek() <= ' ') break; } return in; } ostream& operator<<(ostream& out, const xnum& v) { out << (v.len == 0 ? 0 : v[v.len - 1]); for (int i = v.len - 2; i >= 0; i--) for (int j = base / 10; j > 0; j /= 10) out << v[i] / j % 10; return out; }int dn, hd[52], un, hu[52];void get_convex_hull(point p[], int n, int pol[], int& m) { sort(p, p + n); dn = un = 2; hd[0] = hu[0] = 0; hd[1] = hu[1] = 1; for (int i = 2; i < n; ++i) { while (dn > 1 && sgn((p[hd[dn - 1]] - p[hd[dn - 2]]) * (p[i] - p[hd[dn - 1]])) <= 0) --dn; while (un > 1 && sgn((p[hu[un - 1]] - p[hu[un - 2]]) * (p[i] - p[hu[un - 1]])) >= 0) --un; hd[dn++] = hu[un++] = i; } m = 0; for (int i = 0; i < dn - 1; ++i) pol[m++] = hd[i]; for (int i = un - 1; i > 0; --i) pol[m++] = hu[i];}int n, m, pol[52];point p[52];bool vis[52][52], vis2[52][52][52];xnum ans[52][52], ans2[52][52][52];int get_count(const point& p1, const point& p2, const point& p3) { int cnt = 0; for (int i = 0; i < n; ++i) { if (sgn((p2 - p1) * (p[i] - p1)) > 0 && sgn((p3 - p2) * (p[i] - p2)) > 0 && sgn((p1 - p3) * (p[i] - p3)) > 0) ++cnt; } return cnt;}void calc(int a, int b, int c) { if (vis2[a][b][c]) return; vis2[a][b][c] = true; ans2[a][b][c] = 0; if (vis2[b][c][a]) { ans2[a][b][c] = ans2[b][c][a]; return; } if (vis2[c][a][b]) { ans2[a][b][c] = ans2[c][a][b]; return; } bool f = false; for (int i = 0; i < n; ++i) { if (sgn((p[b] - p[a]) * (p[i] - p[a])) > 0 && sgn((p[c] - p[b]) * (p[i] - p[b])) > 0 && sgn((p[a] - p[c]) * (p[i] - p[c])) > 0) { calc(a, b, i); calc(b, c, i); calc(c, a, i); ans2[a][b][c] = ans2[a][b][c] + ans2[a][b][i] * ans2[b][c][i] * ans2[c][a][i]; f = true; } } if (!f) ans2[a][b][c] = 1;}void calc(int S, int T) { if (vis[S][T]) return; vis[S][T] = true; if (S == T - 1) { ans[S][T] = 1; } else if (S + 2 == T) { calc(pol[S], pol[S + 1], pol[T]); ans[S][T] = ans2[pol[S]][pol[S + 1]][pol[T]]; } else { ans[S][T] = 0; for (int i = S + 1; i < T; ++i) { calc(S, i); calc(i, T); calc(pol[S], pol[i], pol[T]); ans[S][T] = ans[S][T] + ans[S][i] * ans[i][T] * ans2[pol[S]][pol[i]][pol[T]]; } }}bool solve() { if (scanf("%d", &n) == EOF) return false; for (int i = 0; i < n; ++i) p[i].input(); get_convex_hull(p, n, pol, m); memset(vis, 0, sizeof(vis)); memset(vis2, 0, sizeof(vis2)); calc(0, m - 1); cout << ans[0][m - 1] << endl; return true;}int main() { while (solve()); return 0;}