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 print_field(n: usize, anss: &Vec<(i32, i32)>) {
    for y in 0..2 * n {
        for x in 0..2 * n {
            let mut s = " ";
            for &ans in anss {
                if ans == (x as i32, y as i32) {
                    s = "o";
                    break;
                }
            }
            print!("{}", s);
        }
        println!("");
    }
}

// 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 solve(n: usize, ds: Vec<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 used = vec![vec![false; 2 * n]; 2 * n];
    // 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));
    //     }
    // }
    // 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 as i32, y as i32));
            for &(dx, dy) in xy.iter() {
                for xsign in [-1, 1].iter() {
                    let nx = x as i32 + dx as i32 * xsign;
                    let ny = y as i32 + dy;
                    if nx < 0 || nx >= 2 * n as i32 || ny >= 2 * n as i32 {
                        continue;
                    }
                    used[ny as usize][nx as usize] = true;
                }
            }
            if anss.len() == n * n {
                break 'yloop;
            }
        }
    }
    if anss.len() != n * n {
        anss = vec![];
        let mut used = vec![vec![false; 2 * n]; 2 * n];
        'y2loop: for y in 0..2 * n {
            for x in 0..2 * n {
                if used[y][x] || (x + y) % 2 == 1 {
                    continue;
                }
                anss.push((x as i32, y as i32));
                for &(dx, dy) in xy.iter() {
                    for xsign in [-1, 1].iter() {
                        let nx = x as i32 + dx as i32 * xsign;
                        let ny = y as i32 + dy;
                        if nx < 0 || nx >= 2 * n as i32 || ny >= 2 * n as i32 {
                            continue;
                        }
                        used[ny as usize][nx as usize] = true;
                    }
                }
                if anss.len() == n * n {
                    break 'y2loop;
                }
            }
        }
    }

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

fn main() {
    let n = read::<usize>();
    let mut ds = vec![0; 2];
    ds[0] = read::<i32>();
    ds[1] = read::<i32>();
    solve(n, ds);
}

#[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);
        }
    }
}

#[test]
fn search() {
    for n in 1..30 {
        for d1 in 1..30 {
            for d2 in d1 + 1..30 {
                solve(n, vec![d1, d2]);
            }
        }
    }
}