#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

long K;
typedef struct pos_t {long x; long y;} POS;
typedef struct path_t {POS pos; struct path_t *next;} PATH;
POS goal;
PATH *cp;
long hits=0;

long mlength(POS , POS );

int main(int argc, char *argv[]) {
	int sr;
	int i, j;
	POS orig;
	long km;
	long n;
	POS p;
	PATH path;
	int intersect(POS , int , POS , int , POS *);
	POS move_n(POS, POS);
	POS ip, ip2;
	void add_path(POS);
	void print_path(PATH *);

	orig.x=0; orig.y=0;
	path.pos.x = 0; path.pos.y = 0;
	path.next = NULL;
	cp = &path;

	sr=scanf("%ld", &K);
	sr=scanf("%ld %ld", &goal.x, &goal.y);

//fprintf(stderr, "K=%ld, X=%ld, Y=%ld\n", K, goal.x, goal.y);
//fflush(stderr);

	km = mlength(orig, goal)%K;
	n = mlength(orig, goal)/K;
//printf("km=%ld\n", km);
//printf("n=%ld\n", n);
	if (mlength(orig, goal)%2) { // ゴールまでの距離が奇数の場合
		if (K%2 == 0) { // 1打の距離が偶数の場合はクリアできない
			printf("-1\n"); fflush(stdout);
			return 0;
		}
	}


// ゴールまでの距離が1打の距離のちょうどn倍
	if (km==0) {
		p = move_n(orig, goal);
		printf("%ld\n", hits);
		print_path(path.next);
		fflush(stdout);
		return 0;
	}

//	if (K%2 && mlength(orig, goal)%2==0 || n == 0) n++;
//	if (K%2 && n%2==0 || n == 0) n++;
	if (K%2 && n%2==mlength(orig, goal)%2 || n == 0) n++;
	if (mlength(orig, goal)%2) {
// ゴールまでの距離が奇数の場合 1打の距離は奇数 nは奇数
// origから距離n*Kとgoalから距離Kとの交点を求める
// (origとgoalの距離はn*K+α)
//printf("ゴールまでの距離が奇数の場合\n");
		if (intersect(orig, n*K, goal, K, &ip)) {
//printf("ip=(%ld,%ld)\n", ip.x, ip.y);
			p = move_n(orig, ip);
			add_path(goal);
			printf("%ld\n", hits);
			print_path(path.next);
			fflush(stdout);
			return 0;
		} else {
//printf("ip=(%ld,%ld) @\n", ip.x, ip.y);
			if (intersect(ip, K, goal, K, &ip2)) {
				p = move_n(orig, ip);
				p = move_n(ip, ip2);
				add_path(goal);
				printf("%ld\n", hits);
				print_path(path.next);
				fflush(stdout);
				return 0;
			}
		}
	} else { // ゴールまでの距離が偶数の場合
//printf("ゴールまでの距離が偶数の場合 n=%ld, K=%ld\n", n, K);
		if (intersect(orig, n*K, goal, K, &ip)) {
//printf("ip=(%ld,%ld)\n", ip.x, ip.y);
			p = move_n(orig, ip);
			add_path(goal);
			printf("%ld\n", hits);
			print_path(path.next);
			fflush(stdout);
			return 0;
		}
	}


//fprintf(stderr, "error\n");
//fflush(stderr);

	printf("%ld\n", hits);
	print_path(path.next);

	return 0;

}
long mlength(POS p1, POS p2) {
	long ml;

	ml = labs(p1.x-p2.x);
	ml += labs(p1.y-p2.y);
	return ml;
}

void add_path(POS po) {
	PATH *npath;

//printf("add_path(%ld,%ld)\n", po.x, po.y);

	if (mlength(cp->pos , po) != K) {
		fprintf(stderr, "illegal move (%ld,%ld) -> (%ld,%ld)",
			cp->pos.x, cp->pos.y, po.x, po.y);
		fflush(stderr);
	}
	hits++;
	npath = (PATH *)malloc(sizeof(PATH));
	npath->pos = po;
	npath->next = NULL;
	cp->next = npath;
	cp = npath;
}

// 2点から一定の距離にある場所が交わる点
// 複数あるので、最初に見つかったものとする
// p1から距離l1とp2から距離l2にある線が交わる点を求める
// 交わらない場合は0を返し、p1の周囲とp2の周囲を距離Kで結ぶための
// p1の周囲上の点を求める
int intersect(POS p1, int l1, POS p2, int l2, POS *ip) {
	POS pp1[4], pp2[4];
	int i,j;
	int ret1, ret2;
	int ipos(POS , POS , POS, POS, POS *, int);

//printf("intersect((%ld,%ld), %d, (%ld,%ld), %d,_)\n", p1.x, p1.y, l1, p2.x, p2.y,l2);
// 点の偶奇と距離の偶奇が合わない場合は交わらない
	if ( labs((p1.x+p1.y+l1)%2) != labs((p2.x+p2.y+l2)%2)) ret1 = 0;
	else ret1 = 1;

	pp1[0].x = p1.x;    pp1[0].y = p1.y+l1;
	pp1[1].x = p1.x+l1; pp1[1].y = p1.y;
	pp1[2].x = p1.x;    pp1[2].y = p1.y-l1;
	pp1[3].x = p1.x-l1; pp1[3].y = p1.y;
	pp2[0].x = p2.x;    pp2[0].y = p2.y+l2;
	pp2[1].x = p2.x+l2; pp2[1].y = p2.y;
	pp2[2].x = p2.x;    pp2[2].y = p2.y-l2;
	pp2[3].x = p2.x-l2; pp2[3].y = p2.y;

	for (i=0; i<4; i++) {
		for (j=0; j<4; j++) {
			ret2 = ipos(pp1[i], pp1[(i+1)%4], pp2[j], pp2[(j+1)%4], ip, ret1);
			if (ret2) return ret1;
		}
	}
	return 0;

}
// 線分pa1:pa2と線分pb1:pb2の交わる点を求める
// 線分の傾きは1または-1で固定
// ni==0の場合は交点の座標が整数にならないがもっとも近い点を設定する
int ipos(POS pa1, POS pa2, POS pb1, POS pb2, POS *ip, int ni) {
	int aa,ab;
	long ba,bb;
	POS is;
	void pswap(POS *, POS *);

// 線分の端点2点のX座標が昇順になるように正規化
	if (pa1.x > pa2.x) {
		pswap(&pa1, &pa2);
	}
	if (pb1.x > pb2.x) {
		pswap(&pb1, &pb2);
	}
// それぞれの線分の傾き
	aa = (pa1.x-pa2.x)/(pa1.y-pa2.y);
	ab = (pb1.x-pb2.x)/(pb1.y-pb2.y);
// それぞれの線分の切片
	ba = pa1.y-aa*pa1.x;
	bb = pb1.y-ab*pb1.x;

//printf("(%ld,%ld)-(%ld,%ld) x (%ld,%ld)-(%ld,%ld)\n", pa1.x,pa1.y, pa2.x,pa2.y,pb1.x,pb1.y, pb2.x,pb2.y);
//printf("aa=%d, ab=%d, ba=%ld, bb=%ld\n", aa, ab, ba, bb);

// 傾きが同じ場合は線分が重なるか(切片が同じか)をチェック
	if (aa==ab) {
		if (ba != bb) { // 切片が異なる場合は重ならない
			return 0;
		}
		// 線分の重なりがあるか
		if (pa1.x <= pb1.x && pb1.x <= pa2.x) {  // pa1-pa2 の間にpb1がある
			ip->x = pb1.x; ip->y = pb1.y; return 1;
		}
		if (pa1.x <= pb2.x && pb2.x <= pa2.x) {  // pa1-pa2 の間にpb2がある
			ip->x = pb2.x; ip->y = pb2.y; return 1;
		}
		if (pb1.x <= pa1.x && pa1.x <= pb2.x) {  // pb1-pb2 の間にpa1がある
			ip->x = pa1.x; ip->y = pa1.y; return 1;
		}
		if (pb1.x <= pa2.x && pa2.x <= pb2.x) {  // pb1-pb2 の間にpa2がある
			ip->x = pa2.x; ip->y = pa2.y; return 1;
		}
		return 0;
	}
// 交点を求める(傾きが異なる場合: aa!=ab)
	is.y = (ba+bb)/2;  // 交点のY座標は切片の中点
	is.x = (is.y-ba)/aa; // is.y = aa*is.x + ba (Y=aX+b)
	if (pb1.x <= is.x && is.x <= pb2.x &&
		pa1.x <= is.x && is.x <= pa2.x) { // 交点が線分上にあるか
//printf("交点が線分上にある\n");
		ip->x = is.x;
		ip->y = is.y;
		return 1;
	}
	return 0;
}
void pswap(POS *p1, POS *p2) {
	long t;

	t = p1->x;
	p1->x = p2->x;
	p2->x = t;
	t = p1->y;
	p1->y = p2->y;
	p2->y = t;

}
// ゴールまでの距離が1打の距離のn倍
POS move_n(POS cpos, POS gl) {
	long dx, dxm;
	long dy, dym;
	long n;

//printf("move_n((%ld,%ld)->(%ld,%ld))\n", cpos.x, cpos.y, gl.x, gl.y );

	n = mlength(cpos, gl)/K;

	while (1) {
		dx = gl.x - cpos.x;
		dy = gl.y - cpos.y;
		if (dx==0 && dy==0) break;

		if (labs(dx)>labs(dy)) {
			dxm = K*dx/(labs(dx)+labs(dy));
			dym = (K-labs(dxm))*(dy<0?-1:1);
		} else {
			dym = K*dy/(labs(dx)+labs(dy));
			dxm = (K-labs(dym))*(dx<0?-1:1);
		}
		cpos.x += dxm;
		cpos.y += dym;
		add_path(cpos);
		n--;
		if (n<1) break;
	}
	return cpos;

}

void print_path(PATH *pp) {
	while (pp) {
		printf("%ld %ld\n", pp->pos.x, pp->pos.y);
		pp = pp->next;
	}
}


Measured memory_bytes: 8448