#include<bits/stdc++.h>
using namespace std;
const int maxn=200000;
int sq[555555],d1,d2,xx,yy,p[555555],cnt,n,col[555555],msk[555555],pos,sum[5],id;
int cnt1,cnt2,cpt,pa[555555],val[555555];
pair<int,int> v1[1111],v2[1111];
int root(int x)
{
	if (pa[x]==x) return x;
	int rt=root(pa[x]);
	val[x]^=val[pa[x]];
	return pa[x]=rt;
}
void Union(int x,int y)
{
	int rx=root(x),ry=root(y);
	if (rx==ry) return;
	pa[rx]=ry;val[rx]=(1^val[x]^val[y]);
}
void Init()
{
	memset(sq,-1,sizeof(sq));
	for (int i=0;i<=500;i++) sq[i*i]=i;
}
int get(int x,int y)
{
	return (x-1)*n+y;
}
bool In(int x,int y)
{
	return (x>=1 && x<=n && y>=1 && y<=n);
}
void addedge(int x,int y)
{
	Union(x,y);
}
int main()
{
	scanf("%d%d%d",&n,&d1,&d2);
	Init();n<<=1;
	for (int k=0;k<=n;k++)
	{
		if (d1-k*k>=0 && ~sq[d1-k*k]) 
		{
			v1[++cnt1]=make_pair(k,sq[d1-k*k]);
		}
		if (d2-k*k>=0 && ~sq[d2-k*k]) 
		{
			v2[++cnt2]=make_pair(k,sq[d2-k*k]);
		}
	}
	for (int i=1;i<=n*n;i++)
	{
		pa[i]=i;
		val[i]=0;
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=n;j++)
		{
			id=get(i,j);
			for (int k=1;k<=cnt1;k++)
			{
				xx=i+v1[k].first;yy=j+v1[k].second;
				if (In(xx,yy)) addedge(id,get(xx,yy));
				xx=i-v1[k].first;yy=j+v1[k].second;
				if (In(xx,yy)) addedge(id,get(xx,yy));
			}
		}
	}
	for (int i=1;i<=n*n;i++)
	{
		root(i);
		col[i]=val[i];
	}
	for (int i=1;i<=n*n;i++) msk[i]=col[i];
	for (int i=1;i<=n*n;i++)
	{
		pa[i]=i;
		val[i]=0;
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=n;j++)
		{
			id=get(i,j);
			for (int k=1;k<=cnt2;k++)
			{
				xx=i+v2[k].first;yy=j+v2[k].second;
				if (In(xx,yy)) addedge(id,get(xx,yy));
				xx=i-v2[k].first;yy=j+v2[k].second;
				if (In(xx,yy)) addedge(id,get(xx,yy));
			}
		}
	}
	for (int i=1;i<=n*n;i++)
	{
		root(i);
		col[i]=val[i];
	}
	for (int i=1;i<=n*n;i++) msk[i]|=(col[i]<<1);
	for (int i=1;i<=n*n;i++) sum[msk[i]]++;
	for (int i=0;i<4;i++)
	{
		if (sum[i]>=n*n/4) 
		{
			pos=i;
			break;
		}
	}
	for (int i=1;i<=n*n;i++)
	{
		if (cnt==n*n/4) break;
		if (msk[i]==pos) 
		{
			printf("%d %d\n",(i-1)/n,(i-1)%n);
			cnt++;
		}
	}
	return 0;
}
#include <cstdio> 
typedef long long ll;
#define ri register int
namespace io {
	const int SIZE = (1 << 21) + 1;
	char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
	// getchar
	#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
	// print the remaining part
	inline void flush () {
		fwrite (obuf, 1, oS - obuf, stdout);
		oS = obuf;
	}
	// putchar
	inline void putc (char x) {
		*oS ++ = x;
		if (oS == oT) flush ();
	}
	// input a signed integer
	template <class I>
	inline void gi (I &x) {
		for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
		for (x = 0; c <= '9' && c >= '0'; c = gc()) x = (x << 1) + (x << 3) + (c & 15); x *= f;
	}
	// print a signed integer
	template <class I>
	inline void print (I x) {
		if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
		while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
		while (qr) putc (qu[qr --]);
	}
	//no need to call flush at the end manually!
	struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: gi;
using io :: putc;
using io :: print;
const int N=605;
int n,m,col1[N][N],col2[N][N],tag[2][2];
inline void solve(ri d,int col[N][N]){
	ri i,j,k;
	k=0;
	while(d%4==0) d>>=2,++k;
	if(d&1){
		for(i=0;i<m;++i)
			for(j=0;j<m;++j)
				if((i>>k)+(j>>k)&1)
					col[i][j]=1;
	}
	else{
		for(i=0;i<m;++i)
			for(j=0;j<m;++j)
				if((i>>k)&1)
					col[i][j]=1;
	}
}
int main(){
	ri d1,d2,i,j,x,y,cnt;
	gi(n);gi(d1);gi(d2); 
	m=n<<1;
	solve(d1,col1);
	solve(d2,col2);
	for(i=0;i<m;++i)
		for(j=0;j<m;++j)
			++tag[col1[i][j]][col2[i][j]];
	for(i=0;i<=1;++i)
		for(j=0;j<=1;++j)
			if(tag[i][j]>=n*n){
				cnt=0;
				for(x=0;x<m;++x)
					for(y=0;y<m;++y)
						if(col1[x][y]==i&&col2[x][y]==j){
							print(x);putc(' ');print(y);putc('\n');
							if(++cnt==n*n) return 0;
						}
			}
}