#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define sf scanf
#define pf printf
#define pb push_back
#define mp make_pair
#define PI ( acos(-1.0) )
#define mod 1000000007LL
#define IN freopen("nocross.in","r",stdin)
#define OUT freopen("nocross.out","w",stdout)
#define FOR(i,a,b) for(i=a ; i<=b ; i++)
#define DBG pf("Hi\n")
#define INF 2000000000000000000LL
#define i64 long long int
#define eps (1e-8)
#define xx first
#define yy second
#define LOG 19
#define off 2

using namespace __gnu_pbds;
using namespace std ;

typedef tree< i64, null_type, less< i64 >, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

#define maxn 400005

int Map[3005][3005] ;

vector <int> g[maxn] ;
int vis[maxn] ;
vector <int> col[2] ;

void dfs(int u,int l)
{
    col[l].pb(u) ;
    vis[u] = 1 ;
    for( int v: g[u] )
    {
        if(vis[v]) continue ;
        dfs(v,(l^1)) ;
    }
}

vector < pair<int,int> > Do(vector < pair<int,int> > v, int d)
{
    vector < pair<int,int> > dis ;
    for(int i=0 ; i*i <= d ; i++)
    {
        int j = sqrt( d - i*i ) ;
        for( int k = max(j-2,0) ; k<=j+2 ; k++ )
        {
            if( k*k + i*i == d ) j = k ;
        }
        if( j*j + i*i == d ) dis.pb(mp(i,j)) ;
    }

//    for(auto dd: dis) printf("%d: %d %d\n",d,dd.xx,dd.yy) ;

    memset(Map,0,sizeof(Map)) ;

    for(int i=0 ; i<v.size() ; i++)
    {
        Map[ v[i].xx ][ v[i].yy ] = i+1 ;
        g[i+1].clear() ;
    }

    vector < pair<int,int> > Answer ;
    for(int i=0 ; i<v.size() ; i++)
    {
        for(int j=0 ; j<dis.size() ; j++)
        {
            int x = v[i].xx+dis[j].xx  , y = v[i].yy+dis[j].yy ;
            if( x>=0 && y>=0 && Map[x][y] )
            {
                int k = Map[x][y] ;
                g[i+1].pb(k) ; g[k].pb(i+1) ;
            }
            y = v[i].yy-dis[j].yy ;
            if( x>=0 && y>=0 && Map[x][y]  )
            {
                int k = Map[x][y] ;
                g[i+1].pb(k) ; g[k].pb(i+1) ;
            }
        }
    }
    int n = (int)v.size() ;
    for(int i=1 ; i<=n ; i++) vis[i] = 0 ;
    for(int i=1 ; i<=n ; i++)
    {
        if(vis[i] ) continue ;
        col[0].clear() ; col[1].clear() ;
        dfs(i,0) ;
        if( col[0].size() > col[1].size() ) {
            for(int j=0 ; j<col[0].size() ; j++) Answer.pb( v[ col[0][j] - 1 ] ) ;
        }
        else for(int j=0 ; j<col[1].size() ; j++) Answer.pb( v[ col[1][j] -1 ] ) ;
    }

    return Answer;
}

void check( vector <pair<int,int> > v, int d1, int d2 )
{
    for(int i=0 ; i<v.size() ; i++)
    {
        for(int j=i+1 ; j<v.size() ; j++)
        {
            int d = (v[i].xx-v[j].xx)*(v[i].xx-v[j].xx) + (v[i].yy-v[j].yy)*(v[i].yy-v[j].yy) ;
            if( d==d1 || d==d2 )
            {
                printf("NOOOOOOOOOOOOOOO %d %d\n",i+1,j+1) ;
                return ;
            }
        }
    }
    printf("OK\n") ;
}

int main()
{
    int n , d1 ,d2 ;
    scanf("%d %d %d",&n,&d1,&d2) ;

    vector < pair<int,int> > v ;
    for(int i=0 ; i<2*n ; i++)
    {
        for(int j=0 ; j<2*n ; j++)
        {
            v.pb( mp(i,j) ) ;
        }
    }

    v = Do(v,d1) ;

    v = Do(v,d2) ;

//    check(v,d1,d2) ;

    while( (int)v.size() > n*n ) v.pop_back() ;

    for(auto p:v)
    {
        printf("%d %d\n",p.xx,p.yy) ;
    }

    return 0 ;
}


Measured memory_bytes: 122988