// SNIPPET read
pub trait Readable {
    type Output;
    fn words_count() -> usize;
    fn read_words(words: &[&str]) -> Result<Self::Output, String>;
}
#[macro_export]
macro_rules! readable {
    ( $t:ty, $words_count:expr, |$words:ident| $read_words:expr ) => {
        impl Readable for $t {
            type Output = $t;
            fn words_count() -> usize { $words_count }
            fn read_words($words: &[&str]) -> Result<$t, String> {
                Ok($read_words)
            }
        }
    };
}
readable!((), 1, |_ss| ());
readable!(String, 1, |ss| ss[0].to_string());
impl Readable for char {
    type Output = char;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<char, String> {
        let chars: Vec<char> = words[0].chars().collect();
        if chars.len() == 1 {
            Ok(chars[0])
        } else {
            Err(format!("cannot parse `{}` as a char", words[0]))
        }
    }
}
pub struct Chars();
impl Readable for Chars {
    type Output = Vec<char>;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<Vec<char>, String> {
        Ok(words[0].chars().collect())
    }
}
impl Readable for i8 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<i8, String> {
        use std::str::FromStr;
        i8::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(i8))
        })
    }
}
impl Readable for u8 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<u8, String> {
        use std::str::FromStr;
        u8::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(u8))
        })
    }
}
impl Readable for i16 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<i16, String> {
        use std::str::FromStr;
        i16::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(i16))
        })
    }
}
impl Readable for u16 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<u16, String> {
        use std::str::FromStr;
        u16::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(u16))
        })
    }
}
impl Readable for i32 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<i32, String> {
        use std::str::FromStr;
        i32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(i32))
        })
    }
}
impl Readable for u32 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<u32, String> {
        use std::str::FromStr;
        u32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(u32))
        })
    }
}
impl Readable for i64 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<i64, String> {
        use std::str::FromStr;
        i64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(i64))
        })
    }
}
impl Readable for u64 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<u64, String> {
        use std::str::FromStr;
        u64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(u64))
        })
    }
}
impl Readable for isize {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<isize, String> {
        use std::str::FromStr;
        <isize>::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(isize))
        })
    }
}
impl Readable for usize {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<usize, String> {
        use std::str::FromStr;
        <usize>::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(usize))
        })
    }
}
impl Readable for f32 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<f32, String> {
        use std::str::FromStr;
        f32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(usize))
        })
    }
}
impl Readable for f64 {
    type Output = Self;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<f64, String> {
        use std::str::FromStr;
        f64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as {}", words[0], stringify!(usize))
        })
    }
}
#[allow(non_camel_case_types)]
pub struct u8_;
impl Readable for u8_ {
    type Output = u8;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u8::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u16_;
impl Readable for u16_ {
    type Output = u16;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u16::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u32_;
impl Readable for u32_ {
    type Output = u32;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u32::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u64_;
impl Readable for u64_ {
    type Output = u64;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u64::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct usize_;
impl Readable for usize_ {
    type Output = usize;
    fn words_count() -> usize { 1 }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        <usize>::read_words(words).map(|n| n-1)
    }
}
impl<T1: Readable, T2: Readable> Readable for (T1, T2) {
    type Output = (T1::Output, T2::Output);
    fn words_count() -> usize {
        T1::words_count() + T2::words_count()
    }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::words_count());
        let mut start = 0;
        let count1 = T1::words_count();
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let val2 = T2::read_words(&words[start..])?;
        Ok((val1, val2))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable> Readable for (T1, T2, T3) {
    type Output = (T1::Output, T2::Output, T3::Output);
    fn words_count() -> usize {
        T1::words_count() + T2::words_count() + T3::words_count()
    }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::words_count());
        let mut start = 0;
        let count1 = T1::words_count();
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::words_count();
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let val3 = T3::read_words(&words[start..])?;
        Ok((val1, val2, val3))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable> Readable for (T1, T2, T3, T4) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
    fn words_count() -> usize {
        T1::words_count() + T2::words_count() + T3::words_count() + T4::words_count()
    }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::words_count());
        let mut start = 0;
        let count1 = T1::words_count();
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::words_count();
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::words_count();
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let val4 = T4::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, T5: Readable> Readable for (T1, T2, T3, T4, T5) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output);
    fn words_count() -> usize {
        T1::words_count() + T2::words_count() + T3::words_count() + T4::words_count() + T5::words_count()
    }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::words_count());
        let mut start = 0;
        let count1 = T1::words_count();
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::words_count();
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::words_count();
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::words_count();
        let val4 = T4::read_words(&words[start .. start+count4])?;
        start += count4;
        let val5 = T5::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4, val5))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, T5: Readable, T6: Readable> Readable for (T1, T2, T3, T4, T5, T6) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output, T6::Output);
    fn words_count() -> usize {
        T1::words_count() + T2::words_count() + T3::words_count() + T4::words_count() + T5::words_count() + T6::words_count()
    }
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::words_count());
        let mut start = 0;
        let count1 = T1::words_count();
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::words_count();
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::words_count();
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::words_count();
        let val4 = T4::read_words(&words[start .. start+count4])?;
        start += count4;
        let count5 = T5::words_count();
        let val5 = T5::read_words(&words[start .. start+count5])?;
        start += count5;
        let val6 = T6::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4, val5, val6))
    }
}
pub trait ReadableFromLine {
    type Output;
    fn read_line(line: &str) -> Result<Self::Output, String>;
}
fn split_into_words(line: &str) -> Vec<&str> {
    #[allow(deprecated)]
    line.trim_right_matches('\n').split_whitespace().collect()
}
impl<T: Readable> ReadableFromLine for T {
    type Output = T::Output;
    fn read_line(line: &str) -> Result<T::Output, String> {
        let words = split_into_words(line);
        if words.len() != T::words_count() {
            return Err(format!("line `{}` has {} words, expected {}",
                               line, words.len(), T::words_count()));
        }
        T::read_words(&words)
    }
}
fn read_words_into_vec<T: Readable>(words: &[&str], line: &str) -> Result<Vec<T::Output>, String> {
    let n = T::words_count();
    assert_eq!(words.len() % n, 0);
    let mut result = Vec::new();
    for chunk in words.chunks(n) {
        match T::read_words(chunk) {
            Ok(v) => result.push(v),
            Err(msg) => {
                let fragment_msg = if n == 1 {
                    format!("word {}", result.len())
                } else {
                    let l = result.len();
                    format!("words {}-{}", n*l + 1, (n+1) * l)
                };
                return Err(format!(
                    "{} of line `{}`: {}", fragment_msg, line, msg
                ));
            }
        }
    }
    Ok(result)
}
fn split_into_words_for_collection<T: Readable>(
    line: &str, prefix_words_count: usize
) -> Result<Vec<&str>, String> {
    let n = T::words_count();
    let words = split_into_words(line);
    if words.len() < prefix_words_count {
        return Err(
            format!("line `{}` has {} words, expected at least {}",
                    line, words.len(), prefix_words_count)
        );
    }
    if (words.len() - prefix_words_count) % T::words_count() != 0 {
        return Err(
            format!("line `{}` has {} words, expected {} + {}n",
                    line, words.len(), prefix_words_count, n)
        );
    }
    Ok(words)
}
#[macro_export]
macro_rules! readable_collection {
    ($u:ident => $collection_in:ty, $collection_out:ty) => {
        readable_collection!($u: [] => $collection_in, $collection_out);
    };
    ($u:ident : [ $( $bound:path ),* ] => $collection_in:ty, $collection_out:ty) => {
        impl<$u: Readable> ReadableFromLine for $collection_in
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = $collection_out;
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let words = split_into_words_for_collection::<$u>(line, 0)?;
                Ok(read_words_into_vec::<$u>(&words, line)?.into_iter().collect())
            }
        }
        impl<T1: Readable, $u: Readable> ReadableFromLine for (T1, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = T1::words_count();
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let val1 = T1::read_words(&words[..prefix_len])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, $u: Readable> ReadableFromLine for (T1, T2, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2)>::words_count();
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::words_count();
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::words_count();
                let val2 = T2::read_words(&words[start .. start+count2])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, T3: Readable, $u: Readable> ReadableFromLine for (T1, T2, T3, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, T3::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2, T3)>::words_count();
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::words_count();
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::words_count();
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::words_count();
                let val3 = T3::read_words(&words[start .. start+count3])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, val3, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, $u: Readable> ReadableFromLine for (T1, T2, T3, T4, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, T3::Output, T4::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2, T3, T4)>::words_count();
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::words_count();
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::words_count();
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::words_count();
                let val3 = T3::read_words(&words[start .. start+count3])?;
                start += count3;
                let count4 = T4::words_count();
                let val4 = T4::read_words(&words[start .. start+count4])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, val3, val4, rest.into_iter().collect()))
            }
        }
    };
}
readable_collection!(U => Vec<U>, Vec<U::Output>);
pub fn read<T: ReadableFromLine>() -> T::Output {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).unwrap();
    T::read_line(&line).unwrap()
}
#[macro_export]
macro_rules! read {
    () => {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).unwrap();
    };
    ( $pat:pat = $t:ty ) => {
        let $pat = read::<$t>();
    };
    ( $( $pat:pat = $t:ty ),+ ) => {
        read!(($($pat),*) = ($($t),*));
    };
}
#[macro_export]
macro_rules! readls {
    ( $( $pat:pat = $t:ty ),+ ) => {
        $(
            read!($pat = $t);
        )*
    };
}
pub fn readx<T: ReadableFromLine>() -> Vec<T::Output> {
    use std::io::{self, BufRead};
    let stdin = io::stdin();
    let result = stdin.lock().lines().map(|line_result| {
        let line = line_result.expect("read from stdin failed");
        T::read_line(&line).unwrap()
    }).collect();
    result
}
#[macro_export]
macro_rules! readx_loop {
    ( |$pat:pat = $t:ty| $body:expr ) => {
        {
            use std::io::BufRead;
            let stdin = std::io::stdin();
            for line in stdin.lock().lines() {
                let line = line.expect("read from stdin failed");
                let $pat = <$t>::read_line(&line).unwrap();
                $body
            }
        }
    };
    ( |$($pat:pat = $t:ty),*| $body:expr ) => {
        readx_loop!(|($($pat),*) = ($($t),*)| $body);
    };
}
pub fn readn<T: ReadableFromLine>(n: usize) -> Vec<T::Output> {
    use std::io::{self, BufRead};
    let stdin = io::stdin();
    let result: Vec<T::Output> = stdin.lock().lines().take(n).map(|line_result| {
        let line = line_result.expect("read from stdin failed");
        T::read_line(&line).unwrap()
    }).collect();
    if result.len() < n {
        panic!("expected reading {} lines, but only {} lines are read",
               n, result.len());
    }
    result
}
#[macro_export]
macro_rules! readn_loop {
    ( $n:expr, |$pat:pat = $t:ty| $body:expr ) => {
        {
            use std::io::BufRead;
            let stdin = std::io::stdin();
            let mut lock = stdin.lock();
            for _ in 0..$n {
                let mut line = String::new();
                lock.read_line(&mut line).expect("read from stdin failed");
                let $pat = <$t>::read_line(&line).unwrap();
                $body
            }
        }
    };
    ( $n:expr, |$($pat:pat = $t:ty),*| $body:expr ) => {
        readn_loop!($n, |($($pat),*) = ($($t),*)| $body);
    };
}
pub trait Words {
    fn read<T: Readable>(&self) -> T::Output;
}
impl<'a> Words for [&'a str] {
    fn read<T: Readable>(&self) -> T::Output {
        T::read_words(self).unwrap()
    }
}
impl<'a> Words for &'a str {
    fn read<T: Readable>(&self) -> T::Output {
        T::read_words(&[self]).unwrap()
    }
}

// SNIPPET num
pub trait PrimitiveInteger:
    Sized + Ord +
    std::ops::Add<Output=Self> +
    std::ops::Sub<Output=Self> +
    std::ops::Div<Output=Self>
{
    fn one() -> Self;
    fn abs_diff(self, rhs: Self) -> Self;
    fn rem_euclid(self, rhs: Self) -> Self;
}
macro_rules! impl_primitive_integer {
    ( $($t: ty)* ) => { $(
        impl PrimitiveInteger for $t {
            fn one() -> $t {
                1
            }
            fn abs_diff(self, rhs: $t) -> $t {
                if self < rhs { rhs - self } else { self - rhs }
            }
            #[allow(unused_comparisons)]
            fn rem_euclid(self, rhs: $t) -> $t {
                let r = self % rhs;
                if r < 0 {
                    if rhs < 0 { r - rhs } else { r + rhs }
                } else {
                    r
                }
            }
        }
    )* }
}
impl_primitive_integer!(u8 u16 u32 u64 usize i8 i16 i32 i64 isize);
pub trait PrimitiveUnsigned: PrimitiveInteger {
    fn ceil_div(self, rhs: Self) -> Self;
    fn round_div(self, rhs: Self) -> Self;
    fn log2(self) -> Option<Self>;
    fn ceil_log2(self) -> Option<Self>;
    fn sqrt(self) -> Self;
}
macro_rules! impl_primitive_unsigned {
    ( $($t: ty)* ) => { $(
        impl PrimitiveUnsigned for $t {
            fn ceil_div(self, rhs: $t) -> $t {
                (self + rhs - 1) / rhs
            }
            fn round_div(self, rhs: $t) -> $t {
                (self + rhs/2) / rhs
            }
            fn log2(mut self) -> Option<$t> {
                if self == 0 {
                    None
                } else {
                    let mut ans = 0;
                    while self > 1 {
                        ans += 1;
                        self /= 2;
                    }
                    Some(ans)
                }
            }
            fn ceil_log2(self) -> Option<$t> {
                self.log2().map(|x| {
                    (self + ((1<<x) - 1)).log2().unwrap()
                })
            }
            fn sqrt(self) -> $t {
                (self as f64).sqrt() as $t
            }
        }
    )* }
}
impl_primitive_unsigned!(u8 u16 u32 u64 usize);
pub fn gcd(a: u64, b: u64) -> u64 {
    if b == 0 { a } else { gcd(b, a%b) }
}
pub fn bezout(a: i64, b: i64) -> (i64, i64, u64) {
    let (x, y, g) = bezout_sub((a * a.signum()) as u64, (b * b.signum()) as u64);
    (x * a.signum(), y * b.signum(), g)
}
fn bezout_sub(a: u64, b: u64) -> (i64, i64, u64) {
    if b == 0 { (1, 0, a) } else {
        let m = (a / b) as i64;
        let (x, y, g) = bezout_sub(b, a%b);
        (y, x - m*y, g)
    }
}
macro_rules! forward_ref_unop {
    (impl $op:ident, $method:ident for $t:ty) => {
        impl std::ops::$op for &$t {
            type Output = <$t as std::ops::$op>::Output;
            fn $method(self) -> <$t as std::ops::$op>::Output {
                std::ops::$op::$method(*self)
            }
        }
    }
}
macro_rules! forward_ref_binop {
    (impl $op:ident, $method:ident for $t:ty, $u:ty) => {
        impl<'a> std::ops::$op<$u> for &'a $t {
            type Output = <$t as std::ops::$op<$u>>::Output;
            fn $method(self, other: $u) -> <$t as std::ops::$op<$u>>::Output {
                std::ops::$op::$method(*self, other)
            }
        }
        impl std::ops::$op<&$u> for $t {
            type Output = <$t as std::ops::$op<$u>>::Output;
            fn $method(self, other: &$u) -> <$t as std::ops::$op<$u>>::Output {
                std::ops::$op::$method(self, *other)
            }
        }
        impl std::ops::$op<&$u> for &$t {
            type Output = <$t as std::ops::$op<$u>>::Output;
            fn $method(self, other: &$u) -> <$t as std::ops::$op<$u>>::Output {
                std::ops::$op::$method(*self, *other)
            }
        }
    }
}
macro_rules! forward_ref_op_assign {
    (impl $op:ident, $method:ident for $t:ty, $u:ty) => {
        impl std::ops::$op<&$u> for $t {
            fn $method(&mut self, other: &$u) {
                std::ops::$op::$method(self, *other);
            }
        }
    }
}

// SNIPPET dbg
#[macro_export]
#[cfg(local)]
macro_rules! dbg {
    () => {
        {
            use std::io::{self, Write};
            writeln!(io::stderr(), "{}: dbg", line!()).unwrap();
        }
    };
    ($e: expr) => {
        {
            use std::io::{self, Write};
            let result = $e;
            writeln!(io::stderr(), "{}: {} = {:?}",
                     line!(), stringify!($e), result)
                .unwrap();
            result
        }
    }
}
#[macro_export]
#[cfg(not(local))]
macro_rules! dbg {
    () => {};
    ($e: expr) => {
        { $e }
    }
}

// SNIPPET bsearch
pub trait BSearch: Sized {
    type Item;
    fn is_empty(&self) -> bool;
    fn leftmost_item(&self) -> Self::Item;
    fn rightmost_item(&self) -> Self::Item;
    fn middle_item(&self) -> Self::Item;
    fn left_half(&self) -> Self;
    fn right_half(&self) -> Self;
    fn is_bsearch_converged(&self) -> bool;
    fn bsearch_left_max<F>(&self, mut is_left: F) -> Option<Self::Item>
    where
        F: FnMut(&Self::Item) -> bool
    {
        if self.is_empty() {
            None
        } else if !is_left(&self.leftmost_item()) {
            None
        } else {
            let rightmost = self.rightmost_item();
            if is_left(&rightmost) {
                Some(rightmost)
            } else {
                Some(bsearch_left_max_sub(self, is_left))
            }
        }
    }
    fn bsearch_right_min<F>(&self, mut is_right: F) -> Option<Self::Item>
    where
        F: FnMut(&Self::Item) -> bool
    {
        if self.is_empty() {
            None
        } else if !is_right(&self.rightmost_item()) {
            None
        } else {
            let leftmost = self.leftmost_item();
            if is_right(&leftmost) {
                Some(leftmost)
            } else {
                Some(bsearch_right_min_sub(self, is_right))
            }
        }
    }
}
fn bsearch_left_max_sub<Items, T, F>(items: &Items, mut is_left: F) -> T
where
    Items: BSearch<Item=T>,
    F: FnMut(&T) -> bool
{
    if items.is_bsearch_converged() {
        items.leftmost_item()
    } else {
        if is_left(&items.middle_item()) {
            bsearch_left_max_sub(&items.right_half(), is_left)
        } else {
            bsearch_left_max_sub(&items.left_half(), is_left)
        }
    }
}
fn bsearch_right_min_sub<Items, T, F>(items: &Items, mut is_right: F) -> T
where
    Items: BSearch<Item=T>,
    F: FnMut(&T) -> bool
{
    if items.is_bsearch_converged() {
        items.rightmost_item()
    } else {
        if is_right(&items.middle_item()) {
            bsearch_right_min_sub(&items.left_half(), is_right)
        } else {
            bsearch_right_min_sub(&items.right_half(), is_right)
        }
    }
}
impl<T: PrimitiveInteger + Clone> BSearch for std::ops::Range<T> {
    type Item = T;
    fn is_empty(&self) -> bool {
        self.end <= self.start
    }
    fn leftmost_item(&self) -> T {
        self.start.clone()
    }
    fn rightmost_item(&self) -> T {
        self.end.clone() - T::one()
    }
    fn middle_item(&self) -> T {
        (self.start.clone() + self.end.clone()) / (T::one() + T::one())
    }
    fn left_half(&self) -> std::ops::Range<T> {
        self.start.clone()..(self.middle_item() + T::one())
    }
    fn right_half(&self) -> std::ops::Range<T> {
        self.middle_item()..self.end.clone()
    }
    fn is_bsearch_converged(&self) -> bool {
        BSearch::is_empty(self) || self.end.clone() - self.start.clone() <= T::one() + T::one()
    }
}
impl<'a, T> BSearch for &'a [T] {
    type Item = &'a T;
    fn is_empty(&self) -> bool {
        <[T]>::is_empty(self)
    }
    fn leftmost_item(&self) -> &'a T {
        self.first().unwrap()
    }
    fn rightmost_item(&self) -> &'a T {
        self.last().unwrap()
    }
    fn middle_item(&self) -> &'a T {
        self.get(self.len() / 2).unwrap()
    }
    fn left_half(&self) -> &'a [T] {
        &self[..(self.len() / 2 + 1)]
    }
    fn right_half(&self) -> &'a [T] {
        &self[(self.len() / 2)..]
    }
    fn is_bsearch_converged(&self) -> bool {
        self.len() <= 2
    }
}
pub trait SliceBSearch {
    type Item;
    fn bsearch_left_max<F>(&self, is_left: F) -> Option<&Self::Item>
    where
        F: FnMut(&Self::Item) -> bool;
    fn bsearch_index_left_max<F>(&self, is_left: F) -> Option<usize>
    where
        F: FnMut(&Self::Item) -> bool;
    fn bsearch_right_min<F>(&self, is_right: F) -> Option<&Self::Item>
    where
        F: FnMut(&Self::Item) -> bool;
    fn bsearch_index_right_min<F>(&self, is_right: F) -> Option<usize>
    where
        F: FnMut(&Self::Item) -> bool;
}
impl<T> SliceBSearch for [T] {
    type Item = T;
    fn bsearch_left_max<F>(&self, mut is_left: F) -> Option<&T>
    where
        F: FnMut(&T) -> bool
    {
        BSearch::bsearch_left_max(&self, |&x| is_left(x))
    }
    fn bsearch_index_left_max<F>(&self, mut is_left: F) -> Option<usize>
    where
        F: FnMut(&T) -> bool
    {
        (0..self.len()).bsearch_left_max(|&i| {
            let x = unsafe { self.get_unchecked(i) };
            is_left(x)
        })
    }
    fn bsearch_right_min<F>(&self, mut is_right: F) -> Option<&T>
    where
        F: FnMut(&T) -> bool
    {
        BSearch::bsearch_right_min(&self, |&x| is_right(x))
    }
    fn bsearch_index_right_min<F>(&self, mut is_right: F) -> Option<usize>
    where
        F: FnMut(&T) -> bool
    {
        (0..self.len()).bsearch_right_min(|&i| {
            let x = unsafe { self.get_unchecked(i) };
            is_right(x)
        })
    }
}

// END SNIPPETS

use std::cmp;

fn count(aa: &[i64], i: usize, x: i64) -> u64 {
    let a0 = aa[i];
    let aa = &aa[i+1..];
    if a0 < 0 {
        let n = aa.len() as u64;
        n - aa.bsearch_index_right_min(|a| {
            a0*a <= x
        }).map_or(n, |res| res as u64)

    } else {
        aa.bsearch_index_left_max(|a| {
            a0*a <= x
        }).map_or(0, |res| res as u64 + 1)
    }
}

fn main() {
    read!(n = usize, k = u64);
    read!(mut aa = Vec<i64>);
    aa.sort();
    dbg!(&aa);
    let min = *aa.iter().min().unwrap();
    let max = *aa.iter().max().unwrap();
    let edge = cmp::max(min.abs(), max.abs());

    let mut left = -edge*edge;
    let mut right = edge*edge;
    while right - left >= 2 {
        dbg!((left, right));
        let ends = left + right;
        let m = ends / 2;
        let s = (0..n).map(|i| {
            let ans = count(&aa, i, m);
            dbg!((i, m, ans));
            ans
        }).sum::<u64>();
        dbg!((m, s));
        if s >= k {
            right = m;
        } else {
            left = m;
        }
    }

    println!("{}", right);
}


Measured memory_bytes: 15084