Problem:
Score : 800 points

Problem Statement

Takahashi is doing a research on sets of points in a plane.
Takahashi thinks a set S of points in a coordinate plane is a good set when S satisfies both of the following conditions:

The distance between any two points in S is not \sqrt{D_1}.

The distance between any two points in S is not \sqrt{D_2}.

Here, D_1 and D_2 are positive integer constants that Takahashi specified.

Let X be a set of points (i,j) on a coordinate plane where i and j are integers and satisfy 0 ≤ i,j < 2N.

Takahashi has proved that, for any choice of D_1 and D_2, there exists a way to choose N^2 points from X so that the chosen points form a good set.
However, he does not know the specific way to choose such points to form a good set.
Find a subset of X whose size is N^2 that forms a good set.

Constraints

1 ≤ N ≤ 300

1 ≤ D_1 ≤ 2×10^5

1 ≤ D_2 ≤ 2×10^5

All values in the input are integers.

Input

Input is given from Standard Input in the following format:

N D_1 D_2

Output

Print N^2 distinct points that satisfy the condition in the following format:

x_1 y_1
x_2 y_2
:
x_{N^2} y_{N^2}

Here, (x_i,y_i) represents the i-th chosen point.
0 ≤ x_i,y_i < 2N must hold, and they must be integers.
The chosen points may be printed in any order.
In case there are multiple possible solutions, you can output any.

Sample Input 1

2 1 2

Sample Output 1

0 0
0 2
2 0
2 2

Among these points, the distance between 2 points is either 2 or 2\sqrt{2}, thus it satisfies the condition.

Sample Input 2

3 1 5

Sample Output 2

0 0
0 2
0 4
1 1
1 3
1 5
2 0
2 2
2 4

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

//#pragma comment(linker, "/STACK:1024000000,1024000000")
/* vim: set fdm=marker */
//{{{
#define __ return
int ATTENTION() {
	/* pls IGNORE this function and go down and HACK me
	 * read this AFTER contest
	 * this function is empty and it will not be called !
	 */

	http://codeforces.com/group/Pmz2A2x7ES
	/* I created a group there.
	 * I hope with the group, people can finish
	 * past contests, which is important for 
	 * increasing rating.
	 * I am still getting familiar with this function.
	 */
	 __ 0;
}
// deprecated because mac doesn't support this...
/* #include <bits/stdc++.h> */
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <queue>
#include <deque>
#include <bitset>
#include <iterator>
#include <list>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <numeric>
#include <utility>
#include <limits>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int iinf = 0x7fffffff;
const ll linf = ~(1LL<<63);
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef map<ll, int> mli;
typedef map<ll, ll> mll;
template<typename T>
inline T gcd(T a, T b) {
	if(a < 0) return gcd(-a, b);
	if(b < 0) return gcd( a,-b);
	if(a < b) return gcd(b, a);
	if(b == 0) return a;
	return gcd(b, a%b);
}

ll qpow(ll a, ll n, ll mod) {
	a %= mod;
	ll ans = 1LL;
	while(n) {
		if(n & 1) ans = (ans*a % mod);
		a = (a*a % mod);
		n >>= 1;
	}
	return ans;
}

inline ll rev(ll a, ll p) {
	return qpow(a, p - 2, p);
}

#define all(v) v.begin(), v.end()
#define sz(v) v.size()
#define rep(x, st, en) for(int x = st; x < en; x++)
#define rer(x, st, en) for(int x = st; x >= en; x--)
#define pb push_back
#define mp make_pair
#define dbgm(msg, var) cerr<<#msg<<" "<<#var<<" = "<<var<<endl; 
#define dbg(var) cerr<<#var<<" = "<<var<<endl;
#define X first
#define Y second
// build prefix sum
template<typename T>
inline void BPS(T* DST, T* SRC, int N, int s = 0) {
	DST[s] = SRC[s];
	rep(i, 1, N) DST[s + i] = DST[s + i - 1] + SRC[s + i];
}
inline int in() { int x; cin>>x; return x; }
#ifdef ALNDBG
namespace alndbg {
	clock_t s, e;
}
#endif

inline void tic() {
#ifdef ALNDBG
	alndbg::s = clock();
#endif
}

inline void toc() {
#ifdef ALNDBG
	alndbg::e = clock();
	cerr<<1000.0 * (alndbg::e - alndbg::s) / CLOCKS_PER_SEC<<" ms"<<endl;
#endif
}



//}}}

// -------------------- Spliters ------------------------
// BFS求最短路小心vis可能访问过
const int maxn = 302;

vector<int> E1[4*maxn*maxn];
vector<int> E2[4*maxn*maxn];
bool vis[4*maxn*maxn];
int color[4*maxn*maxn][2];
int sqr[220001];

int encode(int x, int y, int N) {
  return x * N + y;
}

void build_graph(int D, int N, vector<int> E[4*maxn*maxn]) {
for(int x = 0; x < 2 * N; x++) {
    for(int y = 0; y < 2 * N; y++) {
      for(int dx = 0; x + dx < 2 * N; dx++) {
        int X = x + dx;
        // (X - x)^2 + (Y - y)^2 = D1
        int dx2 = dx * dx;
        int dy2 = D - dx2;

        if(dy2 < 0) continue;

        int dy = sqr[dy2];

        if(dy < 0) continue;

        int Y = y + dy;

        if(Y >= 2 * N) continue;

        int u = encode(x, y, 2*N);
        int v = encode(X, Y, 2*N);

        assert( (X - x) * (X - x) + (Y - y) * (Y - y) == D);

        E[u].pb(v);
        E[v].pb(u);

        printf("%d, %d - %d, %d\n", x, y, X, Y);

        if(dy == 0) continue;

        Y = y - dy;
        assert( (X - x) * (X - x) + (Y - y) * (Y - y) == D);

        if(Y < 0) continue;

        v = encode(X, Y, 2 * N);

        E[u].pb(v);
        E[v].pb(u);
        printf("%d, %d - %d, %d\n", x, y, X, Y);
      }
    }
  }
}

void dfs(int n, int e12, int c, vector<int> E[4*maxn*maxn]) {
  vis[n] = 1;
  color[n][e12] = c == 1 ? 2 : 1;
  for(auto to : E[n]) {
    if(vis[to]) continue;
    dfs(to, e12, c ^ 1, E);
  }
}

int cnt[3][3];
int main() {
  for(int i = 0; i < 200001;i++) sqr[i] = -1;
  for(int i = 0; i * i <= 200000; i++) sqr[i * i] = i;
  int N, D1, D2;
  scanf("%d%d%d", &N, &D1, &D2);
  build_graph(D1, N, E1);
  build_graph(D2, N, E2);
  rep(i,0,2) {
    memset(vis, 0, sizeof(vis));
    rep(n,0,4*N*N) {
      if(!vis[n]) {
        if(i == 0) dfs(n, i, 0, E1);
        else dfs(n, i, 1, E2);
      }
    }
  }


  int c = -1;
  for(int i = 0; i < 4*N*N; i++) {
    cnt[color[i][0]][color[i][1]]++;
  }
  for(int c1 = 1; c1 <= 2; c1++)
  for(int c2 = 1; c2 <= 2; c2++) {
    if(cnt[c1][c2] < N * N) continue;
    for(int i = 0, cnt = 0; cnt < N * N; i++) {
      if(color[i][0] == c1 && color[i][1] == c2) {
        printf("%d %d\n", i / (2*N), i % ( 2 * N ));
        cnt++;
      }
    }
    return 0;
  }

	return 0;
}
// --USE C++11
// *-USE O2