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;

int solve(int n, int d1, int d2) {
    int m[2*n][2*n];
    memset(m, 0, sizeof(m));
    map<int, int> v;
    for (int i = 0; i * i <= 200010; i++) {
        v[i*i] = i;
    }
    vector<pair<int, int>> u;
    auto f = [&](int d) {
        for (int i = 0; i * i <= d; i++) {
            if (v.count(d-i*i)) {
                u.emplace_back(i, v[d-i*i]);
                u.emplace_back(i, -v[d-i*i]);
                u.emplace_back(-i, v[d-i*i]);
                u.emplace_back(-i, -v[d-i*i]);
            }
        }
    };
    f(d1); f(d2);
    auto in = [&](int x, int y) {
        return 0 <= x && x < 2*n && 0 <= y && y < 2*n;
    };
    set<pair<int, pair<int, int>>> s;
    for (int i = 0; i < 2*n; i++) {
        for (int j = 0; j < 2*n; j++) {
            for (auto &z: u) {
                if (in(i+z.first, j+z.second)) m[i][j]++;
            }
            s.insert({m[i][j], {i, j}});
        }
    }
    int ans = 0;
    vector<int> x, y;
    while (!s.empty()) {
        auto it = *s.begin();
        s.erase(it);
        int i = it.second.first, j = it.second.second;
        if (m[i][j] < it.first) continue;
        ans++;
        x.emplace_back(i), y.emplace_back(j);
        if (ans == n * n) break;
        for (auto &z: u) {
            if (in(i+z.first, j+z.second)) {
                if (m[i+z.first][j+z.second] < 0) continue;
                m[i+z.first][j+z.second] = -1;
                for (auto &p: u) {
                    if (in(i+z.first+p.first, j+z.second+p.second)) {
                        m[i+z.first+p.first][j+z.second+p.second]--;
                        if (m[i+z.first+p.first][j+z.second+p.second] >= 0) {
                            s.insert({m[i+z.first+p.first][j+z.second+p.second], {i+z.first+p.first, j+z.second+p.second}});
                        }
                    }
                }
            }
        }
    }
    //cout << ans << endl;
    assert(ans == n * n);
    for (int i = 0; i < n * n; i++) {
        cout << x[i] << " " << y[i] << "\n";
    }
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, d, e; cin >> n >> d >> e;
    solve(n, d, e);
    return 0;
}