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 Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
  static Scanner sc = new Scanner(System.in);
  static int N;

  public static void main(String[] args) {
    N = sc.nextInt();
    int D1 = sc.nextInt();
    int D2 = sc.nextInt();
    int[][] f1 = solve(D1);
    int[][] f2 = solve(D2);
    PrintWriter writer = new PrintWriter(System.out);
    int c = 0;
    for (int i = 0; i < 2 * N && c < N * N; i++) {
      for (int j = 0; j < 2 * N && c < N * N; j++) {
        if (f1[i][j] == 1 && f2[i][j] == 1) {
          ++c;
          writer.println(i + " " + j);
        }
      }
    }
    writer.flush();
  }

  static int[][] solve(int d) {
    ArrayList<Pair> pairs = new ArrayList<>();
    for (int i = 0; i * i <= d; i++) {
      if (isSq(d - i * i)) {
        int j = (int) Math.sqrt(d - i * i);
        pairs.add(new Pair(i, j));
        pairs.add(new Pair(i, -j));
        pairs.add(new Pair(-i, j));
        pairs.add(new Pair(-i, -j));
      }
    }
    int[][] f = new int[2 * N][2 * N];
    for (int y = 0; y < 2 * N; y++) {
      for (int x = 0; x < 2 * N; x++) {
        if (f[y][x] != 0) continue;
        ArrayList<Integer> cur = new ArrayList<>();
        cur.add((y << 16) | x);
        f[y][x] = 1;
        for (int i = 0; !cur.isEmpty(); i++) {
          ArrayList<Integer> next = new ArrayList<>();
          for (int pos : cur) {
            int cy = pos >> 16;
            int cx = pos & 0xFFFF;
            for (Pair p : pairs) {
              int ny = cy + p.s;
              int nx = cx + p.e;
              if (0 <= ny && ny < 2 * N && 0 <= nx && nx < 2 * N && f[ny][nx] == 0) {
                next.add((ny << 16) | nx);
                f[ny][nx] = i % 2 == 0 ? -1 : 1;
              }
            }
          }
          cur = next;
        }
      }
    }
    return f;
  }

  static boolean isSq(int v) {
    if (v < 0) return false;
    int sqrt = (int) Math.sqrt(v);
    return sqrt * sqrt == v;
  }

  static class Pair {
    int s, e;

    Pair(int s, int e) {
      this.s = s;
      this.e = e;
    }
  }
}