#include <bits/stdc++.h>
#define ll long long

using namespace std;

struct Point
{
  ll x, y;
  Point() {}
  Point(ll _x, ll _y) : x(_x), y(_y) {}
  bool operator==(Point &t)
  {
    return (x == t.x && y == t.y);
  }
  bool operator<(Point &t)
  {
    return (x < t.x || (x == t.x && y < t.y));
  }
  Point operator-(Point &t)
  {
    return Point(x - t.x, y - t.y);
  }
  Point operator+(Point &t)
  {
    return Point(x + t.x, y + t.y);
  }
};

enum Orientation
{
  POSITIVE,
  NEGATIVE,
  COLINEAR
};

Orientation orientation(Point &t0, Point &t1, Point &t2)
{
  long long d = (long long)(t1.x - t0.x) * (long long)(t2.y - t0.y) -
                (long long)(t2.x - t0.x) * (long long)(t1.y - t0.y);
  if (d > 0)
    return POSITIVE;
  else if (d < 0)
    return NEGATIVE;
  else
    return COLINEAR;
}

double area(Point &p1, Point &t2, Point &t3)
{
  return abs((p1.x * (t2.y - t3.y) + t2.x * (t3.y - p1.y) + t3.x * (p1.y - t2.y)) / 2.0);
}

double dot(const Point &t1, const Point &t2)
{
  return t1.x * t2.x + t1.y * t2.y;
}

bool inDisk(Point &t1, Point &t2, Point &p)
{
  return dot(t1 - p, t2 - p) <= 0;
}

bool onLine(Point &t1, Point &t2, Point &t3)
{
  return orientation(t1, t2, t3) == COLINEAR &&
         inDisk(t1, t2, t3);
}

bool pointInTriangle(Point &T1, Point &T2, Point &T3,
                     Point &A)
{
  if (onLine(T1, T2, A) || onLine(T1, T3, A) || onLine(T2, T3, A))
    return true;

  double A1 = area(T1, T2, T3);
  double A2 = area(T1, T2, A);
  double A3 = area(T1, T3, A);
  double A4 = area(T2, T3, A);

  return fabs(A1 - (A2 + A3 + A4)) < 1e-9;
}

bool inPolygon(vector<Point> &polygon, Point &v, int l, int r)
{
  if (r - l == 1)
  {
    return pointInTriangle(polygon[0], polygon[l], polygon[r], v);
  }
  int s = (r + l) / 2;
  if (orientation(polygon[0], polygon[s], v) == POSITIVE)
    return inPolygon(polygon, v, s, r);
  else
    return inPolygon(polygon, v, l, s);
}

bool inPolygon(vector<Point> &polygon, Point &A)
{
  int n = polygon.size();
  if (n < 3)
    return false;
  return inPolygon(polygon, A, 1, n - 1);
}

long long dist(Point &t1, Point &t2)
{
  ll dx = t1.x - t2.x, dy = t1.y - t2.y;
  return dx * dx + dy * dy;
}

void simplePolygon(vector<Point> &points)
{
  auto maxPoint = max_element(begin(points), end(points),
                              [](Point &t1, Point &t2)
                              {
                                return t1.x < t2.x ||
                                       (t1.x == t2.x && t1.y > t2.y);
                              });
  swap(*begin(points), *maxPoint);

  Point &t0 = points[0];

  sort(next(begin(points)), end(points),
       [&t0](Point &t1, Point &t2)
       {
         Orientation o = orientation(t0, t1, t2);
         if (o == COLINEAR)
           return dist(t0, t1) <= dist(t0, t2);
         return o == POSITIVE;
       });

  auto it = prev(end(points));

  while (orientation(*prev(it), *it, t0) == COLINEAR)
    it = prev(it);

  reverse(it, end(points));
}
vector<Point> convexHull(vector<Point> &points)
{
  vector<Point> hull;
  simplePolygon(points);

  hull.push_back(points[0]);
  hull.push_back(points[1]);

  for (int i = 2; i < (int)points.size(); i++)
  {
    while (hull.size() >= 2 &&
           orientation(hull[hull.size() - 2],
                       hull[hull.size() - 1],
                       points[i]) != POSITIVE)
    {
      hull.pop_back();
    }
    hull.push_back(points[i]);
  }

  return hull;
}

ll ans = 0;
Point messi(0, 0);

void process(vector<Point> subset)
{
  int n = subset.size();
  if (n == 1)
  {
    ans += subset[0] == messi;
  }
  else if (n == 2)
  {
    ans += onLine(subset[0], subset[1], messi);
  }
  else if (n == 3)
  {
    ans += pointInTriangle(subset[0], subset[1], subset[2], messi);
  }
  else if (n > 3)
  {

    vector<Point> hull = convexHull(subset);
    int n = hull.size();

    if (n == 2)
    {
      ans += onLine(hull[0], hull[1], messi);
    }
    else if (n == 3)
    {
      ans += pointInTriangle(hull[0], hull[1], hull[2], messi);
    }
    else
    {
      ans += inPolygon(hull, messi);
    }
  }
}

void subsets(const vector<Point> &points, vector<Point> &subset, int index)
{
  if (index == (int)points.size())
  {
    process(subset);
    return;
  }

  subsets(points, subset, index + 1);
  subset.push_back(points[index]);
  subsets(points, subset, index + 1);
  subset.pop_back();
}

void subsets(vector<Point> &points)
{
  vector<Point> subset;

  int index = 0;

  subsets(points, subset, index);
}

int main()
{
  int n;
  cin >> n;
  vector<Point> points(n);
  for (int i = 0; i < n; i++)
    cin >> points[i].x >> points[i].y;

  subsets(points);

  cout << ans << "\n";
  return 0;
}