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: Accepted)

// use std::cmp;
// use std::collections::HashMap;
// use std::collections::HashSet;
// use std::collections::VecDeque;


// const INF: i64 = 1_000_000_000;


fn color(mut d1: i64, mut d2: i64, mut x: i64, mut y: i64) -> i64 {
    while d1 % 4 == 0 && d2 % 4 == 0 {
        d1 /= 4;
        d2 /= 4;
        x /= 2;
        y /= 2;
    }
    if d1 % 4 != 0 && d2 % 4 != 0 {
        return (x % 2) + 2 * (y % 2);
    }
    let (mut d1, d2) = if d2 % 4 == 0 {
        (d2, d1)
    } else {
        (d1, d2)
    };
    let tmp = match d2 % 4 {
        1 => (x + y) % 2,
        2 => x % 2,
        _ => panic!(),
    };
    while d1 % 4 == 0 {
        d1 /= 4;
        x /= 2;
        y /= 2;
    }
    tmp + 2 * match d1 % 4 {
        1 => (x + y) % 2,
        2 => x % 2,
        _ => panic!(),
    }
}

fn main() {
    let cin = stdin();
    let cin = cin.lock();
    let mut sc = Scanner::new(cin);
    let n: i64 = sc.read();
    let d1: i64 = sc.read();
    let d2: i64 = sc.read();
    let grid_size = 2 * n as usize;
    let mut grid = vec![vec![0; grid_size]; grid_size];
    let mut cnt = vec![0; 4];
    for i in 0..grid_size {
        for j in 0..grid_size {
            let k = color(d1, d2, i as i64, j as i64) as usize;
            grid[i][j] = k;
            cnt[k] += 1;
        }
    }
    let mut k = 0;
    loop {
        if cnt[k] >= n * n {
            break;
        }
        k += 1;
    }
    let mut count = 0;
    for i in 0..grid_size {
        for j in 0..grid_size {
            if grid[i][j] == k {
                println!("{} {}", i, j);
                count += 1;
                if count == n * n {
                    return;
                }
            }
        }
    }
}

// thanks, ir5
use std::io::{stdin, Read, StdinLock};
use std::str::FromStr;

struct Scanner<'a> {
    cin: StdinLock<'a>,
}

impl<'a> Scanner<'a> {
    fn new(cin: StdinLock<'a>) -> Scanner<'a> {
        Scanner { cin: cin }
    }

    fn read1<T: FromStr>(&mut self) -> Option<T> {
        let token = self.cin
            .by_ref()
            .bytes()
            .map(|c| c.unwrap() as char)
            .skip_while(|c| c.is_whitespace())
            .take_while(|c| !c.is_whitespace())
            .collect::<String>();
        token.parse::<T>().ok()
    }

    fn read<T: FromStr>(&mut self) -> T {
        self.read1().unwrap()
    }
}