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 std::io::*;
use std::str::FromStr;
use std::collections::BinaryHeap;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn traversal(
    n: usize,
    x: i32,
    y: i32,
    xy: &Vec<(i32, i32)>,
    counts: &mut Vec<Vec<i32>>,
    used: &mut Vec<Vec<bool>>,
    que: &mut BinaryHeap<(i32, i32, i32)>,
    depth: usize,
) {
    for &(dx, dy) in xy.iter() {
        for &ysign in [-1, 1].iter() {
            if dy == 0 && ysign == 1 {
                continue;
            }
            for &xsign in [-1, 1].iter() {
                if dx == 0 && xsign == 1 {
                    continue;
                }
                let nx = x as i32 + dx * xsign;
                let ny = y as i32 + dy * ysign;
                if nx < 0 || nx >= 2 * n as i32 || ny < 0 || ny >= 2 * n as i32
                    || used[ny as usize][nx as usize]
                {
                    continue;
                }
                if depth == 0 {
                    used[ny as usize][nx as usize] = true;
                    traversal(n, nx, ny, xy, counts, used, que, 1)
                } else if depth == 1 {
                    counts[ny as usize][nx as usize] -= 1;
                    assert!(counts[ny as usize][nx as usize] >= 0);
                    que.push((-counts[ny as usize][nx as usize], nx, ny));
                }
            }
        }
    }
}

fn main() {
    let n = read::<usize>();
    let mut ds = vec![0; 2];
    ds[0] = read::<i32>();
    ds[1] = read::<i32>();
    let mut xy = vec![];
    for iter in 0..2 {
        for x in 0..ds[iter] + 1 {
            if x * x > ds[iter] {
                break;
            }
            let rest = ds[iter] - x * x;
            let y = (rest as f64).sqrt() as i32;
            if y * y == rest {
                xy.push((x, y));
            }
        }
    }
    // println!("{:?}", xy);
    let mut counts = vec![vec![0; 2 * n]; 2 * n];
    for y in 0..2 * n {
        for x in 0..2 * n {
            let mut cnt = 0;
            for &(dx, dy) in xy.iter() {
                for &ysign in [-1, 1].iter() {
                    if dy == 0 && ysign == 1 {
                        continue;
                    }
                    for &xsign in [-1, 1].iter() {
                        if dx == 0 && xsign == 1 {
                            continue;
                        }
                        let nx = x as i32 + dx * xsign;
                        let ny = y as i32 + dy * ysign;
                        if nx < 0 || nx >= 2 * n as i32 || ny < 0 || ny >= 2 * n as i32 {
                            continue;
                        }
                        counts[ny as usize][nx as usize] += 1;
                    }
                }
            }
        }
    }
    let mut anss = vec![];
    let mut que = BinaryHeap::<(i32, i32, i32)>::new();
    for y in 0..2 * n {
        for x in 0..2 * n {
            que.push((-counts[y][x], x as i32, y as i32));
        }
    }
    let mut used = vec![vec![false; 2 * n]; 2 * n];
    while let Some((_, x, y)) = que.pop() {
        if used[y as usize][x as usize] {
            continue;
        }
        used[y as usize][x as usize] = true;
        anss.push((x, y));
        traversal(n, x, y, &xy, &mut counts, &mut used, &mut que, 0);
        if anss.len() == n * n {
            break;
        }
    }

    // WA
    // 'yloop: for y in 0..2 * n {
    //     for x in 0..2 * n {
    //         if used[y][x] {
    //             continue;
    //         }
    //         anss.push((x, y));
    //         for &(dx, dy) in xy.iter() {
    //             for xsign in [-1, 1].iter() {
    //                 let nx = x as i32 + dx as i32 * xsign;
    //                 let ny = y + dy;
    //                 if nx < 0 || nx >= 2 * n as i32 || ny >= 2 * n {
    //                     continue;
    //                 }
    //                 used[ny][nx as usize] = true;
    //             }
    //         }
    //         if anss.len() == n * n {
    //             break 'yloop;
    //         }
    //     }
    // }

    assert!(anss.len() == n * n);
    for i in 0..n * n {
        println!("{} {}", anss[i].0, anss[i].1);
    }
}

#[test]
fn search_xy() {
    {
        for d in 1..100 {
            let mut xy = vec![];
            for iter in 0..2 {
                for x in 0..d + 1 {
                    if x * x > d {
                        break;
                    }
                    let rest = d - x * x;
                    let y = (rest as f64).sqrt() as usize;
                    if y * y == rest {
                        xy.push((x, y));
                    }
                }
            }
            println!("{} {} {:?}", d, xy.len(), xy);
        }
    }
}