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

namespace Geo2D{
	typedef long long int ll;
	const double eps = 1e-8;
	const double pi = acos(-1);
	const double inf = 1e100;
	/* Be careful for the criteria for == two doubles */
	/* Relative or Absolute? */
	struct Double{
		double x;
		Double(double x=0):x(x){}
		Double(const Double& rhs){x=rhs.x;}
		Double operator+(const Double& rhs)const{return Double(x+rhs.x);}
		Double& operator+=(const Double& rhs){return x+=rhs.x,*this;}
		Double operator-(const Double& rhs)const{return Double(x-rhs.x);}
		Double& operator-=(const Double& rhs){return x-=rhs.x,*this;}
		Double operator*(const Double& rhs)const{return Double(x*rhs.x);}
		Double& operator*=(const Double& rhs){return x*=rhs.x,*this;}
		Double operator/(const Double& rhs)const{return Double(x/rhs.x);}
		Double& operator/=(const Double& rhs){return x/=rhs.x,*this;}
		Double operator-()const{return Double(-x);}
		Double operator^(const Double& rhs)const{return pow(x,rhs.x);}
		Double operator^(const int& rhs)const{
			double res = 1, base = x;
			int b = rhs;
			while(b){
				if(b&1)	res = res * base;
				b >>= 1;
				base *= base;
			}
			return res;
		}
		Double& operator++(){return ++x,*this;}
		Double& operator--(){return --x,*this;}
		Double operator++(int){Double res(x);return x++,res;}
		Double operator--(int){Double res(x);return x--,res;}
		bool operator==(const Double& rhs)const{return x+eps>=rhs.x&&x<=rhs.x+eps;}
		bool operator!=(const Double& rhs)const{return !(*this==rhs);}
		bool operator<(const Double& rhs)const{return (*this==rhs)?false:x<rhs.x;}
		bool operator>(const Double& rhs)const{return (*this==rhs)?false:x>rhs.x;}
		bool operator<=(const Double& rhs)const{return (*this==rhs)?true:x<rhs.x;}
		bool operator>=(const Double& rhs)const{return (*this==rhs)?true:x>rhs.x;}
		friend ostream & operator << (ostream& os, const Double& rhs){
			os << rhs.x;
			return os;
		}
		friend istream & operator >> (istream& is, Double& rhs){
			is >> rhs.x;
			return is;
		}
		friend Double abs(const Double& rhs){return abs(rhs.x);}
		friend Double sin(const Double& rhs){return sin(rhs.x);}
		friend Double cos(const Double& rhs){return cos(rhs.x);}
		friend Double tan(const Double& rhs){return tan(rhs.x);}
		friend Double asin(const Double& rhs){return asin(rhs.x);}
		friend Double acos(const Double& rhs){return acos(rhs.x);}
		friend Double atan(const Double& rhs){return atan(rhs.x);}
		friend Double atan2(const Double& lhs,const Double& rhs){return atan2(lhs.x,rhs.x);}
		friend Double sqrt(const Double& rhs){return sqrt(rhs.x);}
		friend ll ceil(const Double& rhs){return ceil(rhs.x);}
		friend ll round(const Double& rhs){return round(rhs.x);}
		friend ll floor(const Double& rhs){return floor(rhs.x);}
		friend int sign(const Double& rhs){return (rhs<0)?(-1):(rhs>0);}
	};
	typedef Double T;
	/* To change a point, do P = P.member_function() */
	struct Point{
		T x,y;
		Point(T x=0,T y=0):x(x),y(y){}
		bool operator<(const Point& rhs)const{return x==rhs.x?y<rhs.y:x<rhs.x;}
		bool operator==(const Point& rhs)const{return x==rhs.x&&y==rhs.y;}
		Point operator-()const{return Point(-x,-y);}
		Point operator+(const Point& rhs)const{return Point(x+rhs.x,y+rhs.y);}
		Point operator-(const Point& rhs)const{return Point(x-rhs.x,y-rhs.y);}
		T operator*(const Point& rhs)const{return x*rhs.x+y*rhs.y;}
		Point operator*(const T& rhs)const{return Point(x*rhs,y*rhs);}
		Point operator/(const T& rhs)const{return Point(x/rhs,y/rhs);}
		T operator^(const Point& rhs)const{return x*rhs.y-y*rhs.x;}
		Double len()const{return sqrt(x*x+y*y);}
		T len2()const{return x*x+y*y;}
		Double dist(const Point& rhs)const{Point delta = *this - rhs;return delta.len();}
		T dist2(const Point& rhs)const{Point delta = *this - rhs;return delta.len2();}
		Point norm()const{Double l = len();return *this/l;}
		Point resize(Double l)const{return norm()*l;}
		Point rotpos()const{return Point(-y,x);}
		Point rotneg()const{return Point(y,-x);}
		Point rot(const Double& ang)const{return Point(x*cos(ang)-y*sin(ang),y*cos(ang)+x*sin(ang));}
		/* friend function */
		/* the angle of ABC <= 180 */
		friend Double angle(const Point& A,const Point& B,const Point& C){
			return abs(atan2(abs((A-B)^(C-B)),(A-B)*(C-B)));
		}
		friend ostream & operator << (ostream& os, const Point& rhs){
			os << rhs.x << ' ' << rhs.y;
			return os;
		}
		friend istream & operator >> (istream& is, Point& rhs){
			is >> rhs.x >> rhs.y;
			return is;
		}
	};
	/* ccw, call hull for Pp,Pq beforehand */
	vector<Point> Minkowski(vector<Point>& Pp,vector<Point>& Pq){
		int n=Pp.size(),m=Pq.size();
		vector<Point> Pr;
		Pr.emplace_back(Pp[0]+Pq[0]);
		Pp.emplace_back(Pp[0]);Pq.emplace_back(Pq[0]);
		for(int i=0,j=0;i!=n||j!=m;){
			Point nxt;
			if((j==m)||(i!=n&&((Pp[i+1]-Pp[i])^(Pq[j+1]-Pq[j]))>=0)){
				nxt=Pr.back()+Pp[i+1]-Pp[i];
				i++;
			}
			else{
				nxt=Pr.back()+Pq[j+1]-Pq[j];
				j++;
			}
			while(Pr.size()>=2&&((Pr.back()-nxt)^(Pr[Pr.size()-2]-nxt))==0)
				Pr.pop_back();
			Pr.emplace_back(nxt);
		}
		Pp.pop_back();Pq.pop_back();Pr.pop_back();
		return Pr;
	}
	bool inConvex(vector<Point>& c,const Point& p){
		int L=1,R=c.size()-1;
		if(((p-c[0])^(c[L]-c[0]))>0)	return false;
		if(((p-c[0])^(c[R]-c[0]))<0)	return false;
		while(L<R){
			int mid=(L+R+1)>>1;
			if(((p-c[0])^(c[mid]-c[0]))<=0)	L=mid;
			else	R=mid-1;
		}
		if(L==c.size()-1)	L--;
		return ((p-c[L])^(c[L+1]-c[L]))<=0;
	}
	/* (-pi,pi] */
	Double norm(Double ang){
		ang = ang-round(ang/pi/2)*pi*2;
		if(ang<=-pi)	ang+=2*pi;
		if(ang>pi)	ang-=2*pi;
		return ang;
	}
	struct Line{
		Point s,e;
		Line(Point s=Point(),Point e=Point()):s(s),e(e){}
		Line(Point p,Double ang):s(p){
			ang=norm(ang);
			if(ang==pi/2)	e=s+Point(0,1);
			else if(ang==-pi/2)	e=s-Point(0,1);
			else	e=s+Point(1,tan(ang));
		}
		/* ax+by+c==0 */
		Line(Double a,Double b,Double c){
			if(a==0){
				s=Point(0,-c/b);
				e=Point(1,-c/b);
			}
			else if(b==0){
				s=Point(-c/a,0);
				e=Point(-c/a,1);
			}
			else{
				s=Point(0,-c/b);
				e=Point(-c/a,0);
			}
		}
		bool operator==(const Line& rhs)const{return s==rhs.s&&e==rhs.e;}
		Double len()const{return s.dist(e);}
		T len2()const{return s.dist2(e);}
		Double angle()const{return atan2(e.y-s.y,e.x-s.x);}
		Point projection(const Point& p)const{
			return s+((e-s)*((e-s)*(p-s)))/(e-s).len2();
		}
		Point symmetry(const Point& p)const{
			return projection(p)*2-p;
		}
		/* -1: at left, 0: on line, 1: at right */
		int where(const Point& p)const{
			auto x = (p-s)^(e-s);
			if(x==0)	return 0;
			else if(x>0)	return 1;
			else return -1;
		}
		/* 0: parallel, 1: same, 2: orthogonal, 3: intersect */
		int relation(const Line& l)const{
			if(parallel(l))	return where(l.s)==0;
			else if(orthogonal(l))	return 2;
			else return 3;
		}
		bool onseg(const Point& p)const{return ((p-s)^(e-s))==0&&((p-s)*(p-e))<=0;}
		bool parallel(const Line& l)const{return ((e-s)^(l.e-l.s))==0;}
		bool orthogonal(const Line& l)const{return ((e-s)*(l.e-l.s))==0;}
		/* 0: no intersection, 1: not normal, 2: normal */
		/* *this is line, l is seg */
		int linecrossseg(const Line& l)const{
			int d0 = sign((e-s)^(l.s-s));
			int d1 = sign((e-s)^(l.e-s));
			if((d0^d1)==-2)	return 2;
			return d0==0||d1==0;
		}
		/* 0: no intersection, 1: not normal, 2: normal */
		int segcrossseg(const Line& l)const{
			int d0 = sign((e-s)^(l.s-s));
			int d1 = sign((e-s)^(l.e-s));
			int d2 = sign((l.e-l.s)^(s-l.s));
			int d3 = sign((l.e-l.s)^(e-l.s));
			if((d0^d1)==-2&&(d2^d3)==-2)	return 2;
			return (d0==0&&onseg(l.s))||(d1==0&&onseg(l.e))||(d2==0&&l.onseg(s))||(d3==0&&l.onseg(e));
		}
		Double distasline(const Point& p)const{return abs(((p-s)^(e-s))/len());}
		Double distasseg(const Point& p)const{
			if(((p-s)*(e-s))<0||((p-e)*(s-e))<0)
				return min(s.dist(p),e.dist(p));
			return distasline(p);
		}
		/* both are segs */
		Double distsegseg(const Line& l)const{
			if(segcrossseg(l)!=0)	return 0;
			return min(min(distasseg(l.s),distasseg(l.e)),min(l.distasseg(s),l.distasseg(e)));
		}
		/* *this is line */
		Double distlineseg(const Line& l)const{
			if(linecrossseg(l)==0)
				return min(distasline(l.s),distasline(l.e));
			return 0;
		}

		friend ostream & operator << (ostream& os, const Line& rhs){
			os << rhs.s << ' ' << rhs.e;
			return os;
		}
		friend istream & operator >> (istream& is, Line& rhs){
			is >> rhs.s >> rhs.e;
			return is;
		}
		friend Point intersectLL(const Line& l,const Line& r){
			Double s1=(r.e-r.s)^(l.s-r.s), s2=-((r.e-r.s)^(l.e-r.s));
			return (l.s*s2+l.e*s1)/(s1+s2);
		}
	};
	/* not necessary convex */
	struct Polygon:vector<Point>{
		bool isconvex()const{
			bool flagl=false,flagr=false;
			for(int i=0;i<size();i++){
				int j=(i+1)%size(),k=(j+1)%size();
				auto z=(at(i)-at(j))^(at(k)-at(j));
				if(z<0)	flagl=true;
				if(z>0)	flagr=true;
				if(flagl&&flagr)	return false;
			}
			return true;
		}
		/* negative then clockwise, ccw if positive */
		T area2()const{
			T res=0;
			for(int i=0;i<size();i++)
				res+=(at(i)^at((i+1)%size()));
			return res;
		}
		Double area()const{return abs(area2())/2;}
		Double circum()const{
			Double res=0;
			for(int i=0;i<size();i++)
				res+=at(i).dist(at((i+1)%size()));
			return res;
		}
		/* 3: as vertex, 2: onseg, 1: interior, 0: exterior */
		int relation(const Point& p)const{
			int n=size();
			for(int i=0;i<n;i++)
				if(p==at(i))
					return 3;
			int cnt=0;
			for(int i=0;i<n;i++){
				Point s=at(i),e=at((i+1)%n);
				if(Line(s,e).onseg(p))	return 2;
				if(s.y-e.y>0)	s=at((i+1)%n),e=at(i);
				if(p.y>=e.y||p.y<s.y)	continue;
				if(Line(s,e).where(p)==-1)	cnt++;
			}
			return cnt&1;
		}
	};
	struct Convex:Polygon{
		/* P should contain at least two "different" points */
		Convex(vector<Point> P={},bool border=false){
			if(P.size()<=1)	clear();
			sort(P.begin(),P.end());
			emplace_back(P[0]),emplace_back(P[1]);
			for(int i=2;i<P.size();i++){
				if(border)
					while(size()>=2&&((back()-at(size()-2))^(P[i]-at(size()-2)))<0)
						pop_back();
				else
					while(size()>=2&&((back()-at(size()-2))^(P[i]-at(size()-2)))<=0)
						pop_back();
				emplace_back(P[i]);
			}
			for(int i=P.size()-2,t=size();i>=0;i--){
				if(border)
					while(size()>t&&((back()-at(size()-2))^(P[i]-at(size()-2)))<0)
						pop_back();
				else
					while(size()>t&&((back()-at(size()-2))^(P[i]-at(size()-2)))<=0)
						pop_back();
				emplace_back(P[i]);
			}
			pop_back();
			if(size()<=1||(size()==2&&at(0)==at(1)))	clear();
		}
	};
}
/* End of Geo2D */

using namespace Geo2D;

/* LightOJ 1203: angle
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int T;
	cin>>T;
	for(int t=1;t<=T;t++){
		double ans = inf;
		int n;
		cin>>n;
		vector<Point> res(n);
		for(int i=0;i<n;i++)
			cin>>res[i].x>>res[i].y;
		res = hull(res);
		if(res.empty())	ans = 0;
		else{
			for(int i=0;i<res.size();i++){
				int j =(i+1)%res.size(),k=(j+1)%res.size();
				ans = min(ans,angle(res[i],res[j],res[k]));
			}
		}
		cout<<fixed<<setprecision(10);
		cout<<"Case "<<t<<": "<<ans/pi*180<<endl;
	}
}
*/

/* LibreOJ 2459
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n, m, q;
    cin >> n >> m >> q;
    vector<Point> Pp(n), Pq(m);
    for (int i = 0; i < n; i++) cin >> Pp[i].x >> Pp[i].y;
    for (int i = 0; i < m; i++) {
        cin >> Pq[i].x >> Pq[i].y;
        Pq[i].x = -Pq[i].x;
        Pq[i].y = -Pq[i].y;
    }
    Pp = hull(Pp), Pq = hull(Pq);
    vector<Point> Pr = Minkowski(Pp, Pq);
    while (q--) {
        Point P;
        cin >> P.x >> P.y;
        cout << inConvex(Pr, P) << '\n';
    }
}
*/



/* Aizu CGL 1 A */
/* Aizu CGL 1 B */
/*
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	Point s,e;
	cin>>s.x>>s.y>>e.x>>e.y;
	Line L(s,e);
	int q;
	cin>>q;
	while(q--){
		Point p;
		cin>>p.x>>p.y;
		// p = L.projection(p);
		p = L.symmetry(p);
		cout<<fixed<<setprecision(15)<<p.x<<' '<<p.y<<'\n';
	}
}
*/

/* Aizu CGL 1 C */
/*
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	Line L;
	cin>>L;
	int q;
	cin>>q;
	while(q--){
		Point p2;
		cin>>p2;
		int w = L.where(p2);
		if(w==-1)
			cout<<"COUNTER_CLOCKWISE\n";
		else if(w==1)
			cout<<"CLOCKWISE\n";
		else{
			if(L.onseg(p2))
				cout<<"ON_SEGMENT\n";
			else if((L.e-L.s)*(p2-L.s) > 0)
				cout<<"ONLINE_FRONT\n";
			else
				cout<<"ONLINE_BACK\n";
		}
	}
}
*/

/* Aizu CGL 2 A */
/*
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int q;
	cin>>q;
	while(q--){
		Line L1,L2;
		cin>>L1>>L2;
		int r = L1.relation(L2);
		if(r==3)
			cout<<0<<'\n';
		else if(r==2)
			cout<<1<<'\n';
		else
			cout<<2<<'\n';
	}
}
*/

/* Aizu CGL 2 B */
/*
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int q;
	cin>>q;
	while(q--){
		Line L1,L2;
		cin>>L1>>L2;
		int r = L1.segcrossseg(L2);
		if(r==0)
			cout<<0<<'\n';
		else
			cout<<1<<'\n';
	}
}
*/

/* Aizu CGL 2 C */
/*
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int q;
	cin>>q;
	while(q--){
		Line L1,L2;
		cin>>L1>>L2;
		auto P = intersectLL(L1,L2);
		cout<<fixed<<setprecision(15)<<P<<'\n';
	}
}
*/

/* Aizu CGL 2 D */
/*
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int q;
	cin>>q;
	while(q--){
		Line L1,L2;
		cin>>L1>>L2;
		cout<<fixed<<setprecision(15)<<L1.distsegseg(L2)<<'\n';
	}
}
*/

/* Aizu CGL 3 A */
/* Aizu CGL 3 B */
/* Aizu CGL 3 C */
/*
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	Polygon Poly;
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		Point nxt;
		cin>>nxt;
		Poly.emplace_back(nxt);
	}
	int q;
	cin>>q;
	while(q--){
		Point P;
		cin>>P;
		int x=Poly.relation(P);
		if(x>=2)	cout<<1<<'\n';
		else if(x==1)	cout<<2<<'\n';
		else	cout<<0<<'\n';
	}
	// cout<<Poly.isconvex()<<endl;
	// cout<<fixed<<setprecision(1)<<Poly.area()<<endl;
}
*/

/* Aizu CGL 4 A */
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int n;
	cin>>n;
	vector<Point> P(n);
	for(int i=0;i<n;i++)
		cin>>P[i];
	Convex C(P,true);
	int m=0;
	for(int i=0;i<C.size();i++)
		if(C[i].y<C[m].y||(C[i].y==C[m].y&&C[i].x<C[m].x))
			m=i;
	rotate(C.begin(),C.begin()+m,C.end());
	cout<<C.size()<<'\n';
	for(auto it:C)
		cout<<it<<'\n';
}



Measured memory_bytes: 7324