/* Header {{{ */
#include <bits/stdc++.h>
using namespace std;

typedef long long readtype;
typedef long long var;
typedef long double let;

readtype read() {
  readtype a = 0, c = getchar(), s = 0;
  while (!isdigit(c)) s |= c == '-', c = getchar();
  while (isdigit(c)) a = a * 10 + c - 48, c = getchar();
  return s ? -a : a;
}

#ifdef LOCAL_LOGGER
#define logger(...) fprintf(stderr, __VA_ARGS__)
#define abortif(v, ...) if (v) {logger("Error in Line %d, Function '%s()'.\nInfo: ", __LINE__, __FUNCTION__); logger(__VA_ARGS__); exit(0);}
#else
#define logger(...);
#define abortif(v, ...);
#endif
/* }}} */

const let EPS = 1e-8;
const let Pi = acos(-1.0);

int sign(let x) { return (x < -EPS) ? -1 : (x > EPS ? 1 : 0); }

struct Point {
  let x, y;

  friend Point operator + (Point a, Point b) {
    return (Point) {a.x + b.x, a.y + b.y};
  }

  friend Point operator - (Point a, Point b)  {
    return (Point) {a.x - b.x, a.y - b.y};
  }

  Point operator ~ () { return (Point) {x, -y}; }

  friend int sTimes(Point a, Point b) {
    return sign(Times(a, b));
  }

  friend let Times(Point a, Point b) {
    return a.x * b.y - a.y * b.x;
  }

  Point Rotate(let sink, let cosk) {
    return (Point) {
      x * cosk - y * sink, x * sink + y * cosk
    };
  }

  let dist() {
    return sqrt(x * x + y * y);
  }

};

bool CampByYX(Point a, Point b) {
  if (sign(a.y - b.y) == 0) return sign(a.x - b.x) < 0;
  return sign(a.y - b.y) < 0;
}

typedef Point Vec;

struct Polygon {
  vector<Point> p;

  Point &operator [](int k) { return p.at(k); }
  void push(Point pt) { p.push_back(pt); }
  int size() { return p.size(); }
  void pop() { p.pop_back(); }

  void Rotate(let sink, let cosk) {
    for (size_t i = 0; i < p.size(); ++i)
      p[i] = p[i].Rotate(sink, cosk);
  }

  void Rotate(let k) {
    return Rotate(sin(k), cos(k));
  }

  void Rotate(Vec v) {
    let z = v.dist();
    return Rotate(v.y / z, v.x / z);
  }

  friend Polygon GetConvexHull(Polygon poly) {

    sort(poly.p.begin(), poly.p.end(), CampByYX);

    let angle = ((let) rand() / RAND_MAX) * Pi;
    poly.Rotate(angle);
    Polygon res;

    int cnt = -1;
    for (int i = 0; i < poly.size(); ++i) {
      while (cnt > 0 && sTimes(res[cnt] - res[cnt - 1], poly[i] - res[cnt]) < 0)
        res.pop(), cnt--;
      res.push(poly[i]);
      cnt++;
    }

    int downhull_cnt = cnt;

    for (int i = poly.size() - 2; i >= 0; --i) {
      while (cnt > downhull_cnt && 
          sTimes(res[cnt] - res[cnt - 1], poly[i] - res[cnt]) < 0)
        res.pop(), cnt--;
      res.push(poly[i]);
      cnt++;
    }

    res.pop();
    res.Rotate(-angle);

    return res;
  }

  void Echo() {
    printf("%d\n", size());
    for (int i = 0; i < size(); ++i) {
      if (sign(p[i].x) == 0) p[i].x = 0;
      if (sign(p[i].y) == 0) p[i].y = 0;
      printf("%.0Lf %.0Lf\n", p[i].x, p[i].y);
    }
  }
};

Point ReadPoint() {
  Point p;
  scanf("%Lf%Lf", &p.x, &p.y);
  return p;
}

Polygon ReadPolygon() {
  Polygon poly;
  int g = read();
  for (int i = 1; i <= g; ++i)
    poly.push(ReadPoint());
  return poly;
}

int main() {
// #ifndef ONLINE_JUDGE
//   freopen("CGL_4_A.in", "r", stdin);
//   freopen("CGL_4_A.out", "w", stdout);
// #endif
// #ifdef LOCAL_LOGGER
//   freopen("CGL_4_A.log", "w", stderr);
// #endif
  srand(time(0));
  Polygon poly = ReadPolygon();
  Polygon res = GetConvexHull(poly);
  res.Echo();
  return 0;
}

/* ==== Makefile ==== {{{
CompileAndRun:
	make Compile
	make Run

Compile:
	g++ -o CGL_4_A CGL_4_A.cpp -g -Wall -DLOCAL_LOGGER

CompileUF:
	g++ -o CGL_4_A CGL_4_A.cpp -g -Wall -DLOCAL_LOGGER -fsanitize=undefined

Run:
	./CGL_4_A < CGL_4_A.in > CGL_4_A.out
==================
}}} */



Measured memory_bytes: 14472