#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-9;
const int N = 100 + 10;
int sig(double x){
    return x<-eps?-1:x>eps;
}
struct point{
    double x,y;
    point(){}
    point(double x,double y):x(x),y(y){}
    void input(){cin>>x>>y;}
    void output(){cout<<x<<' '<<y<<endl;}
    point friend operator + (point a,point b){
        return point(a.x+b.x,a.y+b.y);
    }
    point friend operator - (point a,point b){
        return point(a.x-b.x,a.y-b.y);
    }
    point friend operator * (point a,double b){
        return point(a.x*b,a.y*b);
    }
    point friend operator * (double b,point a){
        return point(a.x*b,a.y*b);
    }
    point friend operator / (point a,double b){
        return point(a.x/b,a.y/b);
    }
    bool friend operator < (point a,point b){
        int t = sig(a.y-b.y);
        if(t) return t==-1;
        return sig(a.x-b.x)==-1;
    }
    double norm(){
        return sqrt(x*x+y*y);
    }
};
double dot(point a,point b){
    return a.x * b.x + a.y * b.y;
}
double det(point a,point b){
    return a.x * b.y - a.y * b.x;
}
point point_proj_line(point p,point a,point b){
    return a + dot(p-a,b-a)/dot(b-a,b-a)*(b-a);
}
point point_refl_line(point p,point a,point b){
    point r = point_proj_line(p,a,b);
    return r + r - p;
}
bool point_on_segment(point p,point a,point b){
    return sig(det(p-a,b-a))==0 && sig(dot(a-p,b-p))<=0;
}
struct line{
    point a,b;
    line(){}
    line(point a,point b):a(a),b(b){}
    void input(){a.input(),b.input();}
};
bool parallel(line a,line b){
    return sig(det(a.b-a.a,b.b-b.a))==0;
}
bool orthogonal(line a,line b){
    return sig(dot(a.b-a.a,b.b-b.a))==0;
}
bool intersect(double l1,double r1,double l2,double r2){
    if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
    return !(sig(r1-l2)==-1 || sig(r2-l1)==-1);
}
bool intersect(point a,point b,point c,point d){
    return intersect(a.x,b.x,c.x,d.x) && intersect(a.y,b.y,c.y,d.y) &&
        sig(det(b-a,c-a))*sig(det(b-a,d-a))<=0 && sig(det(d-c,a-c))*sig(det(d-c,b-c))<=0;
}
bool intersect_strict(point a,point b,point c,point d){
    return sig(det(b-a,c-a))*sig(det(b-a,d-a))<0 && sig(det(d-c,a-c))*sig(det(d-c,b-c))<0;
}
point line_make_point(line a,line b){
    double s1 = det(a.a-b.a,b.b-b.a);
    double s2 = det(a.b-b.a,b.b-b.a);
    return (s1*a.b-s2*a.a)/(s1-s2);
}
point line_make_point(point a,point b,point c,point d){
    return line_make_point(line(a,b),line(c,d));
}
double dist(point a,point b){
    return (a-b).norm();
}
double dis_point_segment(point p,point a,point b){
    if(sig(dot(b-a,p-a))<=0) return dist(p,a);
    if(sig(dot(a-b,p-b))<=0) return dist(p,b);
    return fabs(det(b-a,p-a)/dist(a,b));
}
double dis_segment_segment(point a,point b,point c,point d){
    if(intersect(a,b,c,d)) return 0;
    return min(min(dis_point_segment(a,c,d),dis_point_segment(b,c,d)),
               min(dis_point_segment(c,a,b),dis_point_segment(d,a,b)));
}
struct polygon{
    int n;
    point a[N];
    polygon(){n=0;}
    double area(){
        a[n] = a[0];
        double ans = 0;
        for(int i=0;i<n;i++) ans += det(a[i],a[i+1]);
        return ans / 2.0;
    }
    bool is_convex(){
        a[n] = a[0], a[n+1] = a[1];
        for(int i=0;i<n;i++){
            if(sig(det(a[i+1]-a[i],a[i+2]-a[i+1]))<0) return false;
        }
        return true;
    }
    int point_in(point t){
        a[n] = a[0];
        int num = 0;
        for(int i=0;i<n;i++){
            if(point_on_segment(t,a[i],a[i+1])) return 2;
            int k = sig(det(a[i+1]-a[i],t-a[i]));
            int d1 = sig(a[i].y-t.y);
            int d2 = sig(a[i+1].y-t.y);
            if(k>0&&d1<=0&&d2>0) num++;
            if(k<0&&d2<=0&&d1>0) num--;
        }
        return num!=0;
    }
};
vector<point> convex_hull(vector<point> p){
    int n = p.size(); if(n<=1) return p;
    sort(p.begin(),p.end());
    vector<point> q(n*2);
    int k = 0;
    for(int i=0;i<n;q[k++]=p[i++])
        while(k>1&&sig(det(q[k-1]-q[k-2],p[i]-q[k-1]))<0) k--;
    for(int i=n-2,t=k;i>=0;q[k++]=p[i--])
        while(k>t&&sig(det(q[k-1]-q[k-2],p[i]-q[k-1]))<0) k--;
    q.resize(k-1);
    return q;
}
vector<point> convex_hull_strict(vector<point> p){
    int n = p.size(); if(n<=1) return p;
    sort(p.begin(),p.end());
    vector<point> q(n*2);
    int k = 0;
    for(int i=0;i<n;q[k++]=p[i++])
        while(k>1&&sig(det(q[k-1]-q[k-2],p[i]-q[k-1]))<=0) k--;
    for(int i=n-2,t=k;i>=0;q[k++]=p[i--])
        while(k>t&&sig(det(q[k-1]-q[k-2],p[i]-q[k-1]))<=0) k--;
    q.resize(k-1);
    return q;
}
int main(){
    ios::sync_with_stdio(0);
    cout<<fixed<<setprecision(0);
    vector<point> p;
    int n; cin>>n;
    while(n--){
        point t; t.input(); p.push_back(t);
    }
    p = convex_hull(p);
    cout<<p.size()<<endl;
    for(int i=0;i<p.size();i++){
        p[i].output();
    }
}



Measured memory_bytes: 9284