#include<bits/stdc++.h>
typedef long long ll;
typedef long double ld;
#define rep(i,a,b) for(register ll(i)=(ll)(a);(i)<=(ll)(b);++i)
const ll inf=1e9+7;
#define y1 _y_1_
#ifndef gc
	#define gc getchar
#endif
#ifndef pc
	#define pc putchar
#endif
inline ll read(){ll f=0,x=0;register char c=gc();while(!isdigit(c))f^=c=='-',c=gc();while(isdigit(c))x=(x<<3)+(x<<1)+(c^'0'),c=gc();return x=f?-x:x;}
inline ll read(ll&x){ll f=0;x=0;register char c=gc();while(!isdigit(c))f^=c=='-',c=gc();while(isdigit(c))x=(x<<3)+(x<<1)+(c^'0'),c=gc();return x=f?-x:x;}
inline void writeln(){pc('\n');}
inline void write(ll x){if(x<0)pc('-'),x=-x;if(x>9)write(x/10);pc(x%10+'0');}
inline void writeln(const ll&x){write(x),pc('\n');}
using namespace std;
namespace Computation_Geometry{
	const ld eps=1e-9;
	#define lt(x, y) ((x)<(y)-eps)
	#define gt(x, y) ((x)>(y)+eps)
	#define leq(x, y) ((x)<=(y)+eps)
	#define geq(x, y) ((x)>=(y)-eps)
	#define eq(x, y) (le(x,y)&&ge(x, y))
	struct vec{
		typedef vec point;
		ld x,y;
		inline bool is_zero(){return (abs(x)<=eps)&(abs(y)<=eps);}
		inline void scan(){x=read(),y=read();}
		inline vec(){x=y=0;}
		inline vec(const ld&X,const ld&Y){x=X,y=Y;}
		inline friend vec operator +(const vec&A,const vec&B){return vec(A.x+B.x,A.y+B.y);}
		inline friend vec operator -(const vec&A,const vec&B){return vec(A.x-B.x,A.y-B.y);}
		inline friend bool operator <(const vec&A,const vec&B){return lt(A.x,B.x)||(leq(A.x,B.x)&&lt(A.y,B.y));}
		inline friend vec operator *(const vec&A,const ld&k){return vec(A.x*k,A.y*k);}
		inline friend vec operator /(const vec&A,const ld&k){return A*(1.0/k);}
		inline ld len(){return sqrt(x*x+y*y);}
		inline ld Len(){return x*x+y*y;}
		inline friend ld len(vec A){return A.len();}
		inline friend ld Len(vec A){return A.Len();}
		inline ld len(const ll&X,const ll&Y){return sqrt((x-X)*(x-X)+(y-Y)*(y-Y));}
		inline ld k(){return (x==0)?inf:y/x;}
		inline ld k(const ll&X,const ll&Y){return (x==X)?inf:(y-Y)/(x-X);}
		inline friend ld Dot(const vec&A,const vec&B){return A.x*B.x+A.y*B.y;}
		inline friend ld Cross(const vec&A,const vec&B){return A.x*B.y-B.x*A.y;}
		inline friend ld Theta(vec A,vec B){return acos(Cross(A,B)/A.len()/B.len());}
		inline friend ld Cross(const vec&v,const vec&A,const vec&B){return Cross(A-v,B-v);}
		inline friend ld Dot(const vec&v,const vec&A,const vec&B){return Dot(A-v,B-v);}
		inline friend ll ccw(vec p0,vec p1,vec p2){
			p1=p1-p0,p2=p2-p0;
			if (Cross(p1,p2)>=eps) return 1;//COUNTER_CLOCKWISE
			else if (Cross(p1,p2)<-eps) return -1;//CLOCKWISE
			else if (Dot(p1,p2)<-eps) return 2;//ONLINE_BACK
			else if (p1.len()<p2.len())return -2;//ONLINE_FRONT
			return 0;//ON_SEGMENT
		}
		inline friend ll collinear(const vec u,const vec v,const point P){ld p=Cross(P,u,v);return fabs(p)<=eps?1+((Dot(P,u,v))<=eps):0;}
	};
	typedef vec point;
	typedef vector<vec> polygon;
	struct line{
		ld A,B,C;
		inline line(){A=B=C=0;}
		inline line(const ld&_A,const ld&_B,const ld&_C){A=_A,B=_B,C=_C;}
		inline line(const ld&x1,const ld&y1,const ld&x2,const ld&y2){A=y2-y1,B=x1-x2,C=x2*y1-x1*y2;}
		inline line(const vec&_A,const vec&_B){A=_A.y-_B.y,B=_B.x-_A.x,C=Cross(_A,_B);}
		inline vec Vec(){return vec(A,B);}
		inline friend bool is_on_line(line A,point B){return abs(A.A*B.x+A.B*B.y+A.C)<=eps;}
		inline friend bool parallel(line A,line B){return abs(Cross(A.Vec(),B.Vec()))<=eps;}
		inline friend bool perpendicular(line A,line B){return abs(Dot(A.Vec(),B.Vec()))<=eps;}
		inline friend point intersection(const line A, const line B){return point(A.B*B.C-A.C*B.B,A.C*B.A-A.A*B.C)/(A.A*B.B-A.B*B.A);}
	};
	struct segment{
		ld x1,x2,y1,y2;
		inline point p1(){return vec(x1,y1);}
		inline point p2(){return vec(x2,y2);}
		inline segment(){x1=y1=x2=y2=0;}
		inline segment(const ld&X1,const ld&Y1,const ld&X2,const ld&Y2){x1=X1,y1=Y1,x2=X2,y2=Y2;}
		inline line Line(){return line(x1,y1,x2,y2);}
		inline friend bool is_on_segment(segment A,point B){
			if (!is_on_line(A.Line(),B)) return false;
			return ((A.x1<=B.x&&B.x<=A.x2)||(A.x2<=B.x&&B.x<=A.x1))&&((A.y1<=B.y&&B.y<=A.y2)||(A.y2<=B.y&&B.y<=A.y1));
		}
		inline friend bool is_intersected(segment A,segment B){
			vec a=vec(A.x1,A.y1),b=vec(A.x2,A.y2),c=vec(B.x1,B.y1),d=vec(B.x2,B.y2);
			return ((ccw(a,b,c)*ccw(a,b,d)<=0)&&(ccw(c,d,a)*ccw(c,d,b)<=0));
		}
		inline friend ld Distance_SP(segment s,point p){return fabs(Cross(s.p2()-s.p1(),p-s.p1())/len(s.p2()-s.p1()));}
		inline friend ld distance_SP(segment s,point p){
			point p1=s.p1(),p2=s.p2();
			if(Dot(p2-p1,p-p1)<0.0) return len(p-p1);
			if(Dot(p1-p2,p-p2)<0.0) return len(p-p2);
			return Distance_SP(s,p);
		}
		inline friend ld distance_SS(segment s1,segment s2){return min(min(distance_SP(s1,s2.p1()),distance_SP(s1,s2.p2())),min(distance_SP(s2,s1.p1()),distance_SP(s2,s1.p2())));}
	};
	inline void scan(polygon&P){
		ll n=read();
		rep(i,1,n){
			ll x=read(),y=read();
			P.push_back(vec(x,y));
		}
	}
	inline ld area(const polygon P){
		const ll n=P.size();
		ld ret=Cross(P[n-1],P[0]);
		rep(i,0,n-2) ret+=Cross(P[i],P[i+1]);
		return fabs(ret)/2;
	}
	inline bool is_convex(const polygon P){
		const ll n=P.size();
		rep(i,0,n-1) if (ccw(P[(i+n-1)%n],P[i],P[(i+1)%n])==-1) return 0;
		return 1;
	}
	inline ll contain(polygon P,const vec p){
		const ll n=P.size();
		bool x=false;
		rep(i,0,n-1){
			point a=P[i]-p,b=P[(i+1)%n]-p;
			if(abs(Cross(a,b))<=eps&&Dot(a,b)<=eps) return 1;
			if(a.y>b.y) swap(a,b);
			if(a.y<=eps&&eps<=b.y&&Cross(a,b)>=eps) x=!x;
		}
		return (x?2:0);
	}
	inline polygon convex_hull(polygon P){
		ll n=P.size(),k=0;
		if (n<3) return P;
		sort(P.begin(),P.end());
		polygon p(n<<1);
		for (ll i=0;i<n;p[k++]=P[i++])
			while (k>=2&&Cross(p[k-1]-p[k-2],P[i]-p[k-1])<0) --k;
		for (ll i=n-2,t=k+1;i>=0;p[k++]=P[i--])
			while (k>=t&&Cross(p[k-1]-p[k-2],P[i]-p[k-1])<0) --k;
		p.resize(k-1);
		return p;
	}
}
using namespace Computation_Geometry;
polygon p;
point P;
ll n,m;
signed main(){
	scan(p);
	p=convex_hull(p);
	writeln(n=p.size());
	rep(i,1,n-1)
		if (p[m].y>p[i].y||(p[m].y==p[i].y&&p[m].x>p[i].x)) m=i;
	rep(i,0,n-1)
		write((ll)p[(m+i)%n].x),pc(' '),writeln((ll)p[(m+i)%n].y);
	fclose(stdin);fclose(stdout);return 0;
}


Measured memory_bytes: 15376