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 Rust (1.15.1) (judge verdict: Runtime Error)

use io::*;
use std::cmp::{max, min};

struct Tree {
    have: bool,
    child: Vec<Box<Tree>>,
}

fn dist(x1: i64, y1: i64, x2: i64, y2: i64) -> i64 {
    (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)
}

impl Tree {
    fn new() -> Tree {
        Tree {
            have: false,
            child: vec![],
        }
    }

    fn find(&self, x: i64, y: i64, di: i64, l: i64, u: i64, r: i64, d: i64) -> bool {
        if r - l == 0 {
            return false;
        }

        let mut max_d = 0;
        let mut min_d = 999999999999;

        let d0 = dist(x, y, l, u);
        let d1 = dist(x, y, l, d);
        let d2 = dist(x, y, r, u);
        let d3 = dist(x, y, r, d);

        max_d = max(max_d, d0);
        max_d = max(max_d, d1);
        max_d = max(max_d, d2);
        max_d = max(max_d, d3);

        min_d = min(min_d, d0);
        min_d = min(min_d, d1);
        min_d = min(min_d, d2);
        min_d = min(min_d, d3);

        if !(min_d <= di && di <= max_d) {
            return false;
        }

        if r - l == 1 {
            return self.have;
        }

        let mx = (l + r) / 2;
        let my = (u + d) / 2;

        if self.child.len() > 0 {
            self.child[0].find(x, y, di, l, u, mx, my) || self.child[1].find(x, y, di, l, my, mx, d)
                || self.child[2].find(x, y, di, mx, u, r, my)
                || self.child[3].find(x, y, di, mx, my, r, d)
        } else {
            false
        }
    }

    fn add(&mut self, x: i64, y: i64, l: i64, u: i64, r: i64, d: i64) {
        if r - l == 0 {
            return;
        }

        if !(l <= x && x < r && u <= y && y < d) {
            return;
        }

        if r - l == 1 {
            self.have = true;
            return;
        }

        if self.child.len() == 0 {
            for _ in 0..4 {
                self.child.push(Box::new(Tree::new()));
            }
        }

        let mx = (l + r) / 2;
        let my = (u + d) / 2;

        self.child[0].add(x, y, l, u, mx, my);
        self.child[1].add(x, y, l, my, mx, d);
        self.child[2].add(x, y, mx, u, r, my);
        self.child[3].add(x, y, mx, my, r, d);
    }
}

fn main() {
    let con = read_string();
    let mut sc = Scanner::new(&con);

    let n: i64 = sc.next();
    let d1: i64 = sc.next();
    let d2: i64 = sc.next();

    let mut ans = vec![];
    let mut used = vec![vec![false; 2 * n as usize]; 2 * n as usize];

    let mut tree = Tree::new();

    for ix in 0..2 * n * 2 * n {
        let i = ix / (2 * n);
        let j = ix % (2 * n);

        if used[i as usize][j as usize] {
            continue;
        }

        if tree.find(i, j, d1, 0, 0, 2 * n, 2 * n) || tree.find(i, j, d2, 0, 0, 2 * n, 2 * n) {
            continue;
        }

        ans.push((i, j));
        used[i as usize][j as usize] = true;
        tree.add(i, j, 0, 0, 2 * n, 2 * n);

        if ans.len() as i64 == n * n {
            for &(x, y) in ans.iter() {
                println!("{} {}", x, y);
            }
            return;
        }
    }

    unreachable!()
}

//-----

pub mod io {
    use std;
    use std::str::FromStr;

    pub struct Scanner<'a> {
        iter: std::str::SplitWhitespace<'a>,
    }

    impl<'a> Scanner<'a> {
        pub fn new(s: &'a str) -> Scanner<'a> {
            Scanner {
                iter: s.split_whitespace(),
            }
        }

        pub fn next<T: FromStr>(&mut self) -> T {
            let s = self.iter.next().unwrap();
            if let Ok(v) = s.parse::<T>() {
                v
            } else {
                panic!("Parse error")
            }
        }

        pub fn next_vec_len<T: FromStr>(&mut self) -> Vec<T> {
            let n: usize = self.next();
            self.next_vec(n)
        }

        pub fn next_vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.next()).collect()
        }
    }

    pub fn read_string() -> String {
        use std::io::Read;

        let mut s = String::new();
        std::io::stdin().read_to_string(&mut s).unwrap();
        s
    }

    pub fn read_line() -> String {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        s.trim_right().to_owned()
    }
}