Problem:
Score: 500 points

Problem Statement

Does there exist an undirected graph with N vertices satisfying the following conditions?

The graph is simple and connected.

The vertices are numbered 1, 2, ..., N.

Let M be the number of edges in the graph. The edges are numbered 1, 2, ..., M, the length of each edge is 1, and Edge i connects Vertex u_i and Vertex v_i.

There are exactly K pairs of vertices (i,\ j)\ (i < j) such that the shortest distance between them is 2.

If there exists such a graph, construct an example.

Constraints

All values in input are integers.

2 \leq N \leq 100

0 \leq K \leq \frac{N(N - 1)}{2}

Input

Input is given from Standard Input in the following format:

N K

Output

If there does not exist an undirected graph with N vertices satisfying the conditions, print -1.

If there exists such a graph, print an example in the following format (refer to Problem Statement for what the symbols stand for):

M
u_1 v_1
:
u_M v_M

If there exist multiple graphs satisfying the conditions, any of them will be accepted.

Sample Input 1

5 3

Sample Output 1

5
4 3
1 2
3 1
4 5
2 3

This graph has three pairs of vertices such that the shortest distance between them is 2: (1,\ 4), (2,\ 4), and (3,\ 5). Thus, the condition is satisfied.

Sample Input 2

5 8

Sample Output 2

-1

There is no graph satisfying the conditions.

Solution in Rust (1.15.1) (judge verdict: Wrong Answer)

use std::cmp::*;
use std::collections::*;
use std::io::*;
use std::ops::*;
use utils::*;

pub fn main() {
    let i = stdin();
    let mut o = Vec::new();
    run(i.lock(), &mut o);
    stdout().write_all(&o).unwrap();
}

pub fn run<R: BufRead, W: Write>(i: R, o: &mut W) {
    let mut i = CpReader::new(i);
    let (n, k) = i.read::<(usize, usize)>();
    if let Some(uv) = solve(n, k) {
        writeln!(o, "{}", uv.len()).unwrap();
        for (u, v) in uv {
            writeln!(o, "{} {}", u + 1, v + 1).unwrap();
        }
    } else {
        writeln!(o, "-1").unwrap();
    }
}
fn solve(n: usize, k: usize) -> Option<Vec<(usize, usize)>> {
    if n == 2 {
        if k == 0 {
            return Some(vec![(0, 1), (1, 2)]);
        } else {
            return None;
        }
    }
    fn nc2(n: usize) -> usize {
        n * (n - 1) / 2
    }

    fn get(n: usize, c: usize, k: usize, rs: &mut Vec<usize>) -> Option<Vec<(usize, usize)>> {
        if c == k {
            let mut i = 0;
            let mut uv = Vec::new();
            uv.push((i, i + 1));
            i += 1;
            for &r in rs.iter() {
                let i0 = i;
                for _ in 0..r {
                    i += 1;
                    uv.push((i0, i));
                }
                i += 1;
                uv.push((i0, i));
            }
            for _ in 0..n {
                uv.push((i, i + 1));
                i += 1;
            }
            return Some(uv);
        }
        if c > k || n == 0 {
            return None;
        }
        let mut r_max = usize::max_value();
        for i in 0..rs.len() {
            if rs[i] == r_max {
                break;
            }
            rs[i] += 1;
            if let Some(uv) = get(n - 1, c + nc2(rs[i] + 2) - nc2(rs[i] + 1) - 1, k, rs) {
                return Some(uv);
            }
            rs[i] -= 1;
            r_max = rs[i];
        }
        if n >= 2 {
            rs.push(1);
            if let Some(uv) = get(n - 2, c + nc2(3) - nc2(2) - 1, k, rs) {
                return Some(uv);
            }
            rs.pop();
        }
        None
    }
    get(n - 2, n - 2, k, &mut Vec::new())
}

pub mod utils {
    use super::*;

    pub struct CpReader<R: BufRead> {
        r: R,
        b: Vec<u8>,
    }
    impl<R: BufRead> CpReader<R> {
        pub fn new(r: R) -> Self {
            CpReader {
                r: r,
                b: Vec::new(),
            }
        }
        pub fn read_word(&mut self) -> &[u8] {
            self.b.clear();
            let mut consume = 0;
            loop {
                self.r.consume(consume);
                let b = self.r.fill_buf().unwrap();
                assert!(b.len() != 0);
                if let Some(p) = b.iter().position(|&x| x == b' ' || x == b'\n') {
                    self.b.extend_from_slice(&b[..p]);
                    consume = p + 1;
                    break;
                }
                self.b.extend_from_slice(b);
                consume = b.len();
            }
            self.r.consume(consume);
            &self.b
        }
        pub fn read_word_str(&mut self) -> &str {
            unsafe { std::str::from_utf8_unchecked(self.read_word()) }
        }

        pub fn read_line(&mut self) -> &[u8] {
            self.b.clear();
            self.r.read_until(b'\n', &mut self.b).unwrap();
            if self.b.last() == Some(&b'\n') {
                &self.b[..self.b.len() - 1]
            } else {
                &self.b
            }
        }
        pub fn read_line_str(&mut self) -> &str {
            unsafe { std::str::from_utf8_unchecked(self.read_line()) }
        }

        pub fn read<T: CpIn>(&mut self) -> T {
            T::read_from(self)
        }

        pub fn read_vec<T: CpIn>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.read()).collect()
        }
        pub fn read_iter<'a, T: CpIn>(&'a mut self, n: usize) -> CpIter<'a, R, T> {
            CpIter {
                r: self,
                n: n,
                _pd: Default::default(),
            }
        }
    }
    pub struct CpIter<'a, R: BufRead + 'a, T> {
        r: &'a mut CpReader<R>,
        n: usize,
        _pd: std::marker::PhantomData<fn() -> T>,
    }
    impl<'a, R: BufRead, T: CpIn> Iterator for CpIter<'a, R, T> {
        type Item = T;
        fn next(&mut self) -> Option<T> {
            if self.n == 0 {
                None
            } else {
                self.n -= 1;
                Some(self.r.read())
            }
        }
    }

    pub trait CpIn {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self;
    }

    impl CpIn for u64 {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
            read_u64_fast(&mut r.r)
        }
    }
    impl CpIn for i64 {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
            read_i64_fast(&mut r.r)
        }
    }
    impl CpIn for char {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
            let b = r.r.fill_buf().unwrap()[0] as char;
            r.r.consume(1);
            let s = r.r.fill_buf().unwrap()[0];
            assert!(s == b' ' || s == b'\n');
            r.r.consume(1);
            b
        }
    }

    macro_rules! cpin_tuple {
        ($($t:ident),*) => {
            impl<$($t: CpIn),*> CpIn for ($($t),*) {
                fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
                    ($($t::read_from(r)),*)
                }
            }
        };
    }

    macro_rules! cpin_cast {
        ($t_self:ty, $t_read:ty) => {
            impl CpIn for $t_self {
                fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
                    <$t_read>::read_from(r) as $t_self
                }
            }
        };
    }
    macro_rules! cpin_parse {
        ($t:ty) => {
            impl CpIn for $t {
                fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
                    r.read_word_str().parse().unwrap()
                }
            }
        };
    }
    cpin_cast!(usize, u64);
    cpin_cast!(u32, u64);
    cpin_cast!(u16, u64);
    cpin_cast!(i32, i64);
    cpin_cast!(i16, i64);
    cpin_cast!(i8, i64);

    cpin_parse!(f64);

    cpin_tuple!(T1, T2);
    cpin_tuple!(T1, T2, T3);
    cpin_tuple!(T1, T2, T3, T4);
    cpin_tuple!(T1, T2, T3, T4, T5);

    fn read_u64_fast<R: BufRead>(r: &mut R) -> u64 {
        let mut value = 0;
        loop {
            let mut idx = 0;
            let buf_len;
            {
                let buf = r.fill_buf().unwrap();
                buf_len = buf.len();
                assert!(buf_len != 0);
                while idx < buf_len && b'0' <= buf[idx] && buf[idx] <= b'9' {
                    value = value * 10 + (buf[idx] - b'0') as u64;
                    idx += 1;
                }
            }
            if idx < buf_len {
                r.consume(idx + 1);
                return value;
            }
            r.consume(idx);
        }
    }
    fn read_i64_fast<R: BufRead>(r: &mut R) -> i64 {
        let (consume, sign) = match r.fill_buf().unwrap()[0] {
            b'+' => (true, 1),
            b'-' => (true, -1),
            _ => (false, 1),
        };
        if consume {
            r.consume(1);
        }
        read_u64_fast(r) as i64 * sign
    }

    #[derive(Clone, Copy)]
    pub struct Mod(pub usize);

    use std::fmt;
    impl fmt::Debug for Mod {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{:?}", self.0)
        }
    }

    const MOD_BASE: usize = 1000000007;
    const MOD_INV_POW: usize = MOD_BASE - 2;

    impl Mod {
        pub fn new(n: usize) -> Self {
            Mod(n % MOD_BASE)
        }
        pub fn pow(self, mut exp: usize) -> Self {
            let mut b = self;
            let mut r = Mod(1);
            while exp != 0 {
                if exp % 2 == 1 {
                    r *= b;
                }
                exp /= 2;
                b = b * b;
            }
            r
        }
        pub fn inverse_element(self) -> Self {
            self.pow(MOD_INV_POW)
        }

        pub fn comb(n: usize, m: usize) -> Mod {
            let mut v0 = Mod::new(1);
            let mut v1 = Mod::new(1);
            for i in 0..min(m, n - m) {
                v0 *= i + 1;
                v1 *= n - i;
            }
            v1 / v0
        }
    }

    macro_rules! mod_op {
        (($ot:ident, $f:ident), ($ot_a:ident, $f_a:ident), $($rhs:ty : $e:expr,)*) => {
            $(
            impl $ot<$rhs> for Mod {
                type Output = Self;
                fn $f(self, rhs: $rhs) -> Self {
                    ($e)(self, rhs)
                }
            }
            impl $ot_a<$rhs> for Mod {
                fn $f_a(&mut self, rhs: $rhs) {
                    *self = ($e)(*self, rhs)
                }
            }
            )*
        }
    }

    mod_op!(
        (Add, add),
        (AddAssign, add_assign),
        Mod : |l: Mod, r: Mod| Mod::new(l.0 + r.0),
        usize : |l: Mod, r: usize| l + Mod::new(r),
    );

    mod_op!(
        (Mul, mul),
        (MulAssign, mul_assign),
        Mod : |l: Mod, r: Mod| Mod::new(l.0 * r.0),
        usize : |l: Mod, r: usize| l * Mod::new(r),
    );

    mod_op!(
        (Sub, sub),
        (SubAssign, sub_assign),
        Mod : |l: Mod, r: Mod| Mod::new(MOD_BASE + l.0 - r.0),
        usize : |l: Mod, r: usize| l - Mod::new(r),
    );

    mod_op!(
        (Div, div),
        (DivAssign, div_assign),
        Mod : |l: Mod, r: Mod| l * r.inverse_element(),
        usize : |l: Mod, r: usize| l / Mod::new(r),
    );

    // std::cmp::Reverseと同じ
    #[derive(PartialEq, Eq, Copy, Clone)]
    pub struct RevCmp<T>(pub T);

    impl<T: PartialOrd> PartialOrd for RevCmp<T> {
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
            other.0.partial_cmp(&self.0)
        }
    }
    impl<T: Ord> Ord for RevCmp<T> {
        fn cmp(&self, other: &Self) -> Ordering {
            other.0.cmp(&self.0)
        }
    }

    pub struct PascalsTriangle<T> {
        buf: Vec<T>,
        n: usize,
    }

    impl<T: One> PascalsTriangle<T> {
        pub fn new(n: usize) -> Self {
            let mut s = PascalsTriangle {
                buf: vec![T::one()],
                n: 1,
            };
            while s.n <= n {
                let i = s.buf.len() - s.n;
                s.buf.push(T::one());
                for m in 1..s.n {
                    let v = s.buf[i + m - 1] + s.buf[i + m];
                    s.buf.push(v);
                }
                s.buf.push(T::one());
                s.n += 1;
            }
            s
        }
        pub fn get(&mut self, n: usize, m: usize) -> T {
            debug_assert!(n <= self.n);
            debug_assert!(m <= n);
            self.buf[n * (n + 1) / 2 + m]
        }
    }

    pub struct PascalsTriangleIter<T> {
        buf: Vec<T>,
    }
    impl<T: One> PascalsTriangleIter<T> {
        pub fn new(n: usize) -> Self {
            let mut s = PascalsTriangleIter {
                buf: Vec::with_capacity(n + 1),
            };
            for _ in 0..n + 1 {
                s.next();
            }
            s
        }
        pub fn next(&mut self) {
            for i in (1..self.buf.len()).rev() {
                self.buf[i] = self.buf[i] + self.buf[i - 1];
            }
            self.buf.push(T::one());
        }
        pub fn get(&self) -> &[T] {
            &self.buf
        }
    }

    pub struct ModFacts {
        f: Vec<Mod>,
        rf: Vec<Mod>,
    }
    impl ModFacts {
        pub fn new(n: usize) -> Self {
            let mut s = ModFacts {
                f: vec![Mod(0); n + 1],
                rf: vec![Mod(0); n + 1],
            };

            s.f[0] = Mod(1);
            for i in 1..n + 1 {
                s.f[i] = s.f[i - 1] * i;
            }
            s.rf[n] = s.f[n].inverse_element();
            for i in (1..n + 1).rev() {
                s.rf[i - 1] = s.rf[i] * i;
            }
            s
        }
        pub fn fact(&self, n: usize) -> Mod {
            self.f[n]
        }
        pub fn comb(&self, n: usize, c: usize) -> Mod {
            self.f[n] * self.rf[c] * self.rf[n - c]
        }
    }

    pub trait Zero: Add<Output = Self> + Sized + Copy {
        fn zero() -> Self;
    }
    pub trait One: Zero {
        fn one() -> Self;
    }

    macro_rules! impl_zero {
        ($t:ty, $e:expr) => {
            impl Zero for $t {
                fn zero() -> Self {
                    $e
                }
            }
        }
    }
    macro_rules! impl_one {
        ($t:ty, $e1:expr, $e0:expr) => {
            impl One for $t {
                fn one() -> Self {
                    $e1
                }
            }
            impl_zero!($t, $e0);
        };
    }

    impl_one!(usize, 1, 0);
    impl_one!(u32, 1, 0);
    impl_one!(i32, 1, 0);
    impl_one!(f64, 1.0, 0.0);
    impl_one!(Mod, Mod(1), Mod(0));

    pub trait BinarySearchExt<T> {
        fn lower_bound_by<F: Fn(&T) -> bool>(&self, f: F) -> usize;
        fn lower_bound(&self, x: &T) -> usize;
        fn upper_bound(&self, x: &T) -> usize;
    }
    impl<T: Ord> BinarySearchExt<T> for [T] {
        fn lower_bound_by<F: Fn(&T) -> bool>(&self, f: F) -> usize {
            let mut low = 0;
            let mut high = self.len();
            while low < high {
                let mid = (low + high) / 2;
                if f(&self[mid]) {
                    high = mid;
                } else {
                    low = mid + 1;
                }
            }
            low
        }
        fn lower_bound(&self, x: &T) -> usize {
            self.lower_bound_by(|y| x <= y)
        }
        fn upper_bound(&self, x: &T) -> usize {
            self.lower_bound_by(|y| x < y)
        }
    }

    pub trait AtSliceExt<T> {
        fn rotate(&mut self, mid: usize);
    }
    impl<T> AtSliceExt<T> for [T] {
        fn rotate(&mut self, mid: usize) {
            {
                let (l, r) = self.split_at_mut(mid);
                l.reverse();
                r.reverse();
            }
            self.reverse()
        }
    }

    fn divisors<F: FnMut(usize)>(n: usize, mut f: F) {
        fn divisors_by<F: FnMut(usize)>(fs: &[(usize, usize)], mut n: usize, f: &mut F) {
            if fs.is_empty() {
                f(n);
                return;
            }
            let (p, c) = fs[0];
            for _ in 0..c + 1 {
                divisors_by(&fs[1..], n, f);
                n *= p;
            }
        }
        divisors_by(&factorize(n), 1, &mut f)
    }

    fn factorize(mut n: usize) -> Vec<(usize, usize)> {
        assert!(n != 0);

        fn try_push_factor(n: &mut usize, f: usize, fs: &mut Vec<(usize, usize)>) -> bool {
            let mut c = 0;
            while *n % f == 0 {
                *n /= f;
                c += 1;
            }
            if c != 0 {
                fs.push((f, c));
                true
            } else {
                false
            }
        }
        let mut fs = Vec::new();

        try_push_factor(&mut n, 2, &mut fs);
        let mut f = 3;
        let mut end = (n as f64).sqrt() as usize + 1;
        while f < end {
            if try_push_factor(&mut n, f, &mut fs) {
                end = (n as f64).sqrt() as usize + 1;
            }
            f += 2;
        }
        if n != 1 {
            fs.push((n, 1));
        }
        fs
    }

    pub struct VecVec<T> {
        hs: Vec<Option<usize>>,
        vs: Vec<(T, Option<usize>)>,
    }
    impl<T> VecVec<T> {
        #[inline]
        pub fn new(len: usize, capacity: usize) -> Self {
            VecVec {
                hs: vec![None; len],
                vs: Vec::with_capacity(capacity),
            }
        }

        #[inline]
        pub fn push(&mut self, idx: usize, value: T) {
            self.vs.push((value, self.hs[idx]));
            self.hs[idx] = Some(self.vs.len() - 1);
        }

        #[inline]
        pub fn len(&self) -> usize {
            self.hs.len()
        }

        #[inline]
        pub fn get(&self, idx: usize) -> VecVecIter<T> {
            VecVecIter {
                s: self,
                i: self.hs[idx],
            }
        }
    }
    pub struct VecVecIter<'a, T: 'a> {
        s: &'a VecVec<T>,
        i: Option<usize>,
    }
    impl<'a, T: 'a> Iterator for VecVecIter<'a, T> {
        type Item = &'a T;

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            if let Some(i) = self.i {
                self.i = self.s.vs[i].1;
                Some(&self.s.vs[i].0)
            } else {
                None
            }
        }
    }

    pub struct VecVec32<T> {
        hs: Vec<u32>,
        vs: Vec<(T, u32)>,
    }
    impl<T> VecVec32<T> {
        #[inline]
        pub fn new(len: usize, capacity: usize) -> Self {
            assert!(capacity < u32::max_value() as usize);
            VecVec32 {
                hs: vec![0; len],
                vs: Vec::with_capacity(capacity),
            }
        }

        #[inline]
        pub fn push(&mut self, idx: usize, value: T) {
            self.vs.push((value, self.hs[idx]));
            self.hs[idx] = self.vs.len() as u32;
        }

        #[inline]
        pub fn len(&self) -> usize {
            self.hs.len()
        }

        #[inline]
        pub fn get(&self, idx: usize) -> VecVec32Iter<T> {
            VecVec32Iter {
                s: self,
                i: self.hs[idx],
            }
        }
    }
    pub struct VecVec32Iter<'a, T: 'a> {
        s: &'a VecVec32<T>,
        i: u32,
    }
    impl<'a, T: 'a> Iterator for VecVec32Iter<'a, T> {
        type Item = &'a T;

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            if self.i == 0 {
                None
            } else {
                let i = self.i as usize - 1;
                self.i = self.s.vs[i].1;
                Some(&self.s.vs[i].0)
            }
        }
    }

    pub fn gcd(a: usize, b: usize) -> usize {
        fn f(a: usize, b: usize) -> usize {
            let r = a % b;
            if r == 0 {
                b
            } else {
                f(b, r)
            }
        }
        f(max(a, b), min(a, b))
    }

    struct Array2<T> {
        len: (usize, usize),
        items: Vec<T>,
    }
    impl<T> Array2<T> {
        #[inline]
        fn new(len: (usize, usize), value: T) -> Self
        where
            T: Clone,
        {
            Array2 {
                len: len,
                items: vec![value; len.0 * len.1],
            }
        }
        #[inline]
        fn idx(&self, i: (usize, usize)) -> usize {
            assert!(i.0 < self.len.0);
            assert!(i.1 < self.len.1);
            i.0 + i.1 * self.len.0
        }
    }

    impl<T> Index<(usize, usize)> for Array2<T> {
        type Output = T;

        #[inline]
        fn index(&self, index: (usize, usize)) -> &T {
            &self.items[self.idx(index)]
        }
    }
    impl<T> IndexMut<(usize, usize)> for Array2<T> {
        #[inline]
        fn index_mut(&mut self, index: (usize, usize)) -> &mut T {
            let idx = self.idx(index);
            &mut self.items[idx]
        }
    }

    #[derive(PartialEq, PartialOrd)]
    pub struct OrdF64(pub f64);

    impl OrdF64 {
        pub fn new(value: f64) -> Self {
            assert!(!value.is_nan());
            OrdF64(value)
        }
    }

    impl Eq for OrdF64 {}
    impl Ord for OrdF64 {
        fn cmp(&self, other: &Self) -> Ordering {
            self.partial_cmp(&other).unwrap()
        }
    }

    pub fn binary_search<F: Fn(usize) -> bool>(len: usize, f: F) -> usize {
        let mut low = 0;
        let mut high = len;
        while low < high {
            let mid = (low + high) / 2;
            if f(mid) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        low
    }

}