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)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;

#define X first
#define Y second

//#include <boost/unordered_map.hpp>
//using namespace boost;

/*
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> rbtree;
rbtree T;
*/

namespace io{
	const int L = (1 << 20) + 1;
	
	char buf[L], *S , *T, c;
	 
	char getchar() {
		if(S == T) {
			T = (S = buf) + fread(buf, 1, L, stdin);
			return (S == T ? EOF : *S++);
		}
		return *S++;
	}
	
	int inp() {
		int x = 0, f = 1; char ch;
		for(ch = getchar(); !isdigit(ch); ch = getchar())
			if(ch == '-') f = -1;
		for(; isdigit(ch); x = x * 10 + ch - '0', ch = getchar());
		return x * f;
	}
	
	ll inp_ll() {
		ll x = 0; int f = 1; char ch;
		for(ch = getchar(); !isdigit(ch); ch = getchar())
			if(ch == '-') f = -1;
		for(; isdigit(ch); x = x * 10 + ch - '0', ch = getchar());
		return x * f;
	}
	
	char B[25], *outs=B+20, *outr=B+20;
	template<class T>
	inline void print(register T a,register char x=0){
		if(x) *--outs = x, x = 0;
		
		if(!a)*--outs = '0';
		else 
			while(a)
				*--outs = (a % 10) + 48, a /= 10;
		
		if(x)
			*--outs = x;
		
		fwrite(outs, outr - outs , 1, stdout);
		outs = outr;
	}
};

using io :: print;
using io :: inp;
using io :: inp_ll;

const int MAXN = 610;

int n;
vector<pii> v, res;
int u[MAXN][MAXN];

void add(int x, int y)
{
	res.emplace_back(x, y);
	u[x][y] = 1;
	for (auto p : v)
	{
		if (x+p.X < 2*n && y+p.Y < 2*n) u[x+p.X][y+p.Y] = 1;
		if (x+p.X < 2*n && y-p.Y >= 0) u[x+p.X][y-p.Y] = 1;
	}
}

int main()
{
	
	int d1, d2;
	cin >> n >> d1 >> d2;
	if (n == 1)
	{
		puts("0 0");
		return 0;
	}
	for (int i = 0; i*i <= d1; ++ i)
	{
		int j = sqrt(d1-i*i);
		while ((j+1)*(j+1) <= d1) ++ j;
		if (i*i+j*j == d1) v.emplace_back(i, j);
	}
	for (int i = 0; i*i <= d2; ++ i)
	{
		int j = sqrt(d2-i*i);
		while ((j+1)*(j+1) <= d2) ++ j;
		if (i*i+j*j == d2) v.emplace_back(i, j);
	}
	for (int k = 0; k < 2*n; ++ k)
	{
		for (int i = 0; i < 2*n; ++ i)
			for (int j = 0; j < 2*n; ++ j)
				u[i][j] = 0;
		res.clear();
		int cnt = 1;
		add(0, k);
		for (int j = 0; j <= k; ++ j)
			u[0][j] = 1;
		for (int i = 0; i < 2*n; ++ i)
			for (int j = 0; j < 2*n; ++ j)
			{
				if (u[i][j]) continue;
				cnt ++;
				add(i, j);
				if (cnt == n*n)
					goto here;
			}
		here:
		if (cnt == n*n)
		{
			
			for (auto p : res)
				printf("%d %d\n", p.X, p.Y);
			
			return 0;
		}
	}
	for (int i = 1; i <= 1000000000; ++ i)
		printf("%d\n", -1);
	
	return 0;
}