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# (Mono 4.6.2.0) (judge verdict: Runtime Error)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Globalization;
using System.Diagnostics;



class Myon
{
    public Myon() { }
    public static int Main()
    {
        new Myon().calc();
        return 0;
    }


    Scanner cin;


    bool[,] check;

    int H, W;
    bool inside(int y, int x)
    {
        return y >= 0 && x >= 0 && y < H && x < W;
    } 

    void calc()
    {
        /*
        Dictionary<int, int> dic = new Dictionary<int, int>();
        for (int i = 1; i < 300; i+=2)
        {
            for (int j = 1; j < 300; j+=2)
            {
                int ans = i * i + j * j;
                if (!dic.ContainsKey(ans)) dic[ans] = 0;
                dic[ans]++;
            }
        }
        foreach (var item in dic)
        {
            if (item.Value <= 2) continue;
            Console.WriteLine(item.Key + " " + item.Value);
        }
        */

        cin = new Scanner();
        int N = cin.nextInt();
        int D1 = cin.nextInt();
        int D2 = cin.nextInt();

        H = W = N * 2;


        List<Tuple<int, int>> l = new List<Tuple<int, int>>();
        for (int i = 0; i < 2 * N; i++)
        {
            for (int j = 0; j < 2 * N; j++)
            {
                if (i * i + j * j == D1 || i * i + j * j == D2)
                {
                    l.Add(Tuple.Create(i, j));
                    //Console.WriteLine(i + " " + j);
                }
            }
        }



        check = new bool[2 * N, 2 * N];
        List<int> x = new List<int>();
        List<int> y = new List<int>();
        for (int i = 0; i < 2 * N; i++)
        {
            for (int j = 0; j < 2 * N; j++)
            {
                bool ok = true;
                foreach (var item in l)
                {
                    for (int mx = -1; mx <= 1; mx += 2)
                    {
                        int ny = i - item.Item1;
                        int nx = i + mx * item.Item2;
                        if(inside(ny,nx) && check[ny, nx])
                        {
                            ok = false;
                            break;
                        }
                    }
                    if (!ok) break;
                }
                if (ok)
                {
                    x.Add(i);y.Add(j);check[i, j] = true;
                }
            }
        }


        //Console.WriteLine((N * N) + " " + x.Count);
        for (int i = 0; i < N * N; i++)
        {
            Console.WriteLine(x[i] + " " + y[i]);
        }


        /*
        int ystep = -1;
        int xstep = -1;
        for (int x = 1; x <= N; x++)
        {
            for (int y = 1; y <= 2; y++)
            {
                bool ok = true;

                foreach (var t in l)
                {
                    int Y = t.Item1;
                    int X = t.Item2;
                    
                    if (Y >= y * N) continue;
                    if (Y % y != 0) continue;

                    if (Y % (x * y) == 0 && ((Y / (x * y)) % 2 != X % 2)) continue;

                    ok = false;
                    break;
                }

                if (ok)
                {
                    xstep = x;
                    ystep = y;
                    break;
                }
            }
            if (ystep != -1) break;
        }

        if(xstep == -1)
        {
            throw new Exception("!?");
        }

        for (int i = 0; i < N; i++)
        {
            int y = i * ystep;
            for (int j = 0; j < N; j++)
            {
                int x = j * 2;
                if ((j / xstep) % 2 == 1) x += 1;
                Console.WriteLine(x + " " + y);
            }
        }
        */
    }

}






class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        if (i < s.Length) return s[i++];
        string st = Console.ReadLine();
        while (st == "") st = Console.ReadLine();
        s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
        if (s.Length == 0) return next();
        i = 0;
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }
    public int[] ArrayInt(int N, int add = 0)
    {
        int[] Array = new int[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextInt() + add;
        }
        return Array;
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public long[] ArrayLong(int N, long add = 0)
    {
        long[] Array = new long[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextLong() + add;
        }
        return Array;
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }


    public double[] ArrayDouble(int N, double add = 0)
    {
        double[] Array = new double[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextDouble() + add;
        }
        return Array;
    }
}