Problem:
Score : 500 points

Problem Statement

Given are N integers A_1,\ldots,A_N.

We will choose exactly K of these elements. Find the maximum possible product of the chosen elements.

Then, print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Constraints

1 \leq K \leq N \leq 2\times 10^5

|A_i| \leq 10^9

Input

Input is given from Standard Input in the following format:

N K
A_1 \ldots A_N

Output

Print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Sample Input 1

4 2
1 2 -3 -4

Sample Output 1

12

The possible products of the two chosen elements are 2, -3, -4, -6, -8, and 12, so the maximum product is 12.

Sample Input 2

4 3
-1 -2 -3 -4

Sample Output 2

1000000001

The possible products of the three chosen elements are -24, -12, -8, and -6, so the maximum product is -6.

We print this value modulo (10^9+7), that is, 1000000001.

Sample Input 3

2 1
-1 1000000000

Sample Output 3

1000000000

The possible products of the one chosen element are -1 and 1000000000, so the maximum product is 1000000000.

Sample Input 4

10 10
1000000000 100000000 10000000 1000000 100000 10000 1000 100 10 1

Sample Output 4

999983200

Be sure to print the product modulo (10^9+7).

Solution in Rust (1.42.0) (judge verdict: Accepted)


// SNIPPET read
pub trait Readable {
    type Output;
    const WORD_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;
            const WORD_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;
    const WORD_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>;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Vec<char>, String> {
        Ok(words[0].chars().collect())
    }
}
pub struct Bytes();
impl Readable for Bytes {
    type Output = Vec<u8>;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Vec<u8>, String> {
        Ok(words[0].bytes().collect())
    }
}
impl Readable for i8 {
    type Output = Self;
    const WORD_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 i8", words[0])
        })
    }
}
impl Readable for u8 {
    type Output = Self;
    const WORD_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 u8", words[0])
        })
    }
}
impl Readable for i16 {
    type Output = Self;
    const WORD_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 i16", words[0])
        })
    }
}
impl Readable for u16 {
    type Output = Self;
    const WORD_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 u16", words[0])
        })
    }
}
impl Readable for i32 {
    type Output = Self;
    const WORD_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 i32", words[0])
        })
    }
}
impl Readable for u32 {
    type Output = Self;
    const WORD_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 u32", words[0])
        })
    }
}
impl Readable for i64 {
    type Output = Self;
    const WORD_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 i64", words[0])
        })
    }
}
impl Readable for u64 {
    type Output = Self;
    const WORD_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 u64", words[0])
        })
    }
}
impl Readable for isize {
    type Output = Self;
    const WORD_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 isize", words[0])
        })
    }
}
impl Readable for usize {
    type Output = Self;
    const WORD_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 usize", words[0])
        })
    }
}
impl Readable for f32 {
    type Output = Self;
    const WORD_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 f32", words[0])
        })
    }
}
impl Readable for f64 {
    type Output = Self;
    const WORD_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 f64", words[0])
        })
    }
}
#[allow(non_camel_case_types)]
pub struct u8_;
impl Readable for u8_ {
    type Output = u8;
    const WORD_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;
    const WORD_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;
    const WORD_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;
    const WORD_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;
    const WORD_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);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_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);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_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);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_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);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT + T5::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::WORD_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);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT + T5::WORD_COUNT + T6::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::WORD_COUNT;
        let val4 = T4::read_words(&words[start .. start+count4])?;
        start += count4;
        let count5 = T5::WORD_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))
    }
}
impl<T: Readable> Readable for [T; 2] {
    type Output = [T::Output; 2];
    const WORD_COUNT: usize = T::WORD_COUNT * 2;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        Ok([val1, val2])
    }
}
impl<T: Readable> Readable for [T; 3] {
    type Output = [T::Output; 3];
    const WORD_COUNT: usize = T::WORD_COUNT * 3;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        Ok([val1, val2, val3])
    }
}
impl<T: Readable> Readable for [T; 4] {
    type Output = [T::Output; 4];
    const WORD_COUNT: usize = T::WORD_COUNT * 4;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        Ok([val1, val2, val3, val4])
    }
}
impl<T: Readable> Readable for [T; 5] {
    type Output = [T::Output; 5];
    const WORD_COUNT: usize = T::WORD_COUNT * 5;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        let val5 = T::read_words(&words[T::WORD_COUNT*4 .. T::WORD_COUNT*5])?;
        Ok([val1, val2, val3, val4, val5])
    }
}
impl<T: Readable> Readable for [T; 6] {
    type Output = [T::Output; 6];
    const WORD_COUNT: usize = T::WORD_COUNT * 6;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        let val5 = T::read_words(&words[T::WORD_COUNT*4 .. T::WORD_COUNT*5])?;
        let val6 = T::read_words(&words[T::WORD_COUNT*5 .. T::WORD_COUNT*6])?;
        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> {
    line.trim_end_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::WORD_COUNT {
            return Err(format!("line `{}` has {} words, expected {}",
                               line, words.len(), T::WORD_COUNT));
        }
        T::read_words(&words)
    }
}
pub fn read_words_into_vec<T: Readable>(words: &[&str], line: &str) -> Result<Vec<T::Output>, String> {
    let n = T::WORD_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)
}
pub fn split_into_words_for_collection<T: Readable>(
    line: &str, prefix_words_count: usize
) -> Result<Vec<&str>, String> {
    let n = T::WORD_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::WORD_COUNT != 0 {
        return Err(
            format!("line `{}` has {} words, expected {} + {}",
                    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::WORD_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)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_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)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::WORD_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)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::WORD_COUNT;
                let val3 = T3::read_words(&words[start .. start+count3])?;
                start += count3;
                let count4 = T4::WORD_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>();
    };
    ( ! $(,)* ) => {
        let _ = read::<()>();
    };
    ( $pat:pat = $t:ty, $( $rest:tt )+ ) => {
        read_inner!($pat = $t; $($rest)+);
    };
    ( !, $( $rest:tt )+ ) => {
        read_inner!(_ = (); $($rest)+);
    };
}
#[macro_export]
#[doc(hidden)]
macro_rules! read_inner {
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; $pat:pat = $t:ty, $( $rest:tt )* ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , $pat = $t ; $($rest)*);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; !, $( $rest:tt )* ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , _ = () ; $($rest)*);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; $pat:pat = $t:ty ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , $pat = $t ;);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; ! ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , _ = () ;);
    };
    ( $( $pat:pat = $t:ty ),+ ; ) => {
        let ($($pat),+) = read::<($($t),+)>();
    };
}
pub trait ReadableFromChunk {
    type Output;
    fn lines_count() -> usize;
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String>;
}
impl<T1: ReadableFromLine, T2: ReadableFromLine> ReadableFromChunk for (T1, T2) {
    type Output = (T1::Output, T2::Output);
    fn lines_count() -> usize { 2 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        Ok((out1, out2))
    }
}
impl<T1: ReadableFromLine, T2: ReadableFromLine, T3: ReadableFromLine> ReadableFromChunk for (T1, T2, T3) {
    type Output = (T1::Output, T2::Output, T3::Output);
    fn lines_count() -> usize { 3 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        let out3 = T3::read_line(&lines[2])?;
        Ok((out1, out2, out3))
    }
}
impl<T1: ReadableFromLine, T2: ReadableFromLine, T3: ReadableFromLine, T4: ReadableFromLine> ReadableFromChunk for (T1, T2, T3, T4) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
    fn lines_count() -> usize { 4 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        let out3 = T3::read_line(&lines[2])?;
        let out4 = T4::read_line(&lines[3])?;
        Ok((out1, out2, out3, out4))
    }
}
pub fn read_chunk<T: ReadableFromChunk>() -> T::Output {
    let stdin = std::io::stdin();
    let mut handle = stdin.lock();
    read_chunk_from_handle::<T>(&mut handle).unwrap()
}
fn read_chunk_from_handle<T: ReadableFromChunk>(handle: &mut std::io::StdinLock) -> Option<T::Output> {
    use std::io::BufRead;
    let mut lines = vec![String::new(); T::lines_count()];
    let mut first = true;
    for line in &mut lines {
        if handle.read_line(line).unwrap() == 0 && first {
            return None;
        }
        first = false;
    }
    Some(T::read_chunk(&lines).unwrap())
}
#[macro_export]
macro_rules! read_chunk {
    ( $( $pat:pat = $t:ty ),+ ) => {
        let ($($pat),+) = read_chunk::<($($t),+)>();
    };
}
static mut STDIN: Option<std::io::Stdin> = None;
pub struct ReadLines<T: ReadableFromLine> {
    lock: std::io::StdinLock<'static>,
    phantom: std::marker::PhantomData<T>
}
impl<T: ReadableFromLine> Iterator for ReadLines<T> {
    type Item = T::Output;
    fn next(&mut self) -> Option<T::Output> {
        use std::io::BufRead;
        let mut line = String::new();
        if self.lock.read_line(&mut line).unwrap() > 0 {
            Some(T::read_line(&line).unwrap())
        } else {
            None
        }
    }
}
pub fn read_lines<T: ReadableFromLine>() -> ReadLines<T> {
    unsafe {
        if STDIN.is_none() {
            STDIN = Some(std::io::stdin());
        }
    }
    ReadLines {
        lock: unsafe { STDIN.as_ref().unwrap().lock() },
        phantom: std::marker::PhantomData::<T>
    }
}
pub struct ReadChunks<T: ReadableFromChunk> {
    lock: std::io::StdinLock<'static>,
    phantom: std::marker::PhantomData<T>
}
impl<T: ReadableFromChunk> Iterator for ReadChunks<T> {
    type Item = T::Output;
    fn next(&mut self) -> Option<T::Output> {
        read_chunk_from_handle::<T>(&mut self.lock)
    }
}
pub fn read_chunks<T: ReadableFromChunk>() -> ReadChunks<T> {
    unsafe {
        if STDIN.is_none() {
            STDIN = Some(std::io::stdin());
        }
    }
    ReadChunks {
        lock: unsafe { STDIN.as_ref().unwrap().lock() },
        phantom: std::marker::PhantomData::<T>
    }
}
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 utils
#[macro_export]
macro_rules! echo {
    () => {
        println!()
    };
    ($e: expr $(,)?) => {
        println!("{}", $e)
    };
    ($e: expr, $($es: expr),+ $(,)?) => {
        {
            use std::io::Write;
            let stdout = std::io::stdout();
            let mut handle = stdout.lock();
            write!(handle, "{}", $e).unwrap();
            $(
                write!(handle, " {}", $es).unwrap();
            )+
            writeln!(handle).unwrap();
        }
    };
}
pub fn yn(result: bool) {
    if result {
        println!("Yes");
    } else {
        println!("No");
    }
}
#[allow(non_snake_case)]
pub fn YN(result: bool) {
    if result {
        println!("YES");
    } else {
        println!("NO");
    }
}
pub fn exit(msg: impl std::fmt::Display) -> ! {
    println!("{}", msg);
    std::process::exit(0)
}
#[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 op_macros
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 modp
pub type ModPBase = u64;
pub type ModPModulus = u32;
static mut MODULUS: ModPBase = 0;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ModP {
    base: ModPBase
}
impl ModP {
    pub unsafe fn set_mod(modulus: ModPModulus) -> Result<(), String> {
        if modulus <= 1 {
            return Err(format!("{} is not a prime number.", modulus));
        }
        if modulus >= 4 {
            if modulus % 2 == 0 || modulus % 3 == 0 {
                return Err(format!("{} is not a prime number.", modulus));
            }
            let mut divisor = 5;
            loop {
                if divisor * divisor > modulus {
                    break;
                }
                if modulus % divisor == 0 {
                    return Err(format!("{} is not a prime number.", modulus));
                }
                divisor += 2;
                if divisor * divisor > modulus {
                    break;
                }
                if modulus % divisor == 0 {
                    return Err(format!("{} is not a prime number.", modulus));
                }
                divisor += 4;
            }
        }
        MODULUS = modulus as ModPBase;
        Ok(())
    }
    pub fn new(n: ModPBase) -> ModP {
        if !cfg!(test) {
            assert!(unsafe { MODULUS } != 0,
                    "Call ModP::set_mod before using ModP.");
        }
        ModP { base: n % unsafe { MODULUS } }
    }
    pub unsafe fn new_unchecked(n: ModPBase) -> ModP {
        ModP { base: n }
    }
    pub fn base(&self) -> ModPBase {
        self.base
    }
    pub fn pow(self, exp: ModPBase) -> ModP {
        if exp == 0 { ModP::new(1) } else {
            let sub = self.pow(exp / 2);
            if exp % 2 == 0 {
                sub * sub
            } else {
                self * sub * sub
            }
        }
    }
    pub fn inv(self) -> ModP {
        assert!(self.base() != 0);
        self.pow(unsafe { MODULUS } - 2)
    }
    pub fn fact_cache() -> FactCache {
        FactCache {
            table: vec![ModP::new(1)]
        }
    }
    pub fn inv_cache() -> InvCache {
        InvCache {
            table: vec![ModP::new(0), ModP::new(1)]
        }
    }
    pub fn pow_cache(base: ModPBase) -> PowCache {
        PowCache {
            base: base,
            table: vec![ModP::new(1)]
        }
    }
    pub fn combinatorics_cache() -> CombinatoricsCache {
        CombinatoricsCache {
            facts: ModP::fact_cache(),
            invs: ModP::inv_cache(),
            finvs: vec![ModP::new(1)],
        }
    }
}
pub fn modp(x: ModPBase) -> ModP {
    ModP::new(x)
}
impl std::fmt::Display for ModP {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.base())
    }
}
impl std::fmt::Debug for ModP {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{} mod P", self.base())
    }
}
impl PartialEq<ModPBase> for ModP {
    fn eq(&self, other: &ModPBase) -> bool {
        self.base() == other % unsafe { MODULUS }
    }
}
impl PartialEq<ModP> for ModPBase {
    fn eq(&self, other: &ModP) -> bool {
        self % unsafe { MODULUS } == other.base() % unsafe { MODULUS }
    }
}
macro_rules! impl_from_signed_for_modp {
    ( $($t: ty)* ) => { $(
        impl From<$t> for ModP {
            fn from(num: $t) -> ModP {
                unsafe { ModP::new_unchecked((num as i64).rem_euclid(MODULUS as i64) as u64) }
            }
        }
    )* }
}
impl_from_signed_for_modp!(i8 i16 i32 i64 isize);
macro_rules! impl_from_unsigned_for_modp {
    ( $($t: ty)* ) => { $(
        impl From<$t> for ModP {
            fn from(num: $t) -> ModP {
                unsafe { ModP::new_unchecked((num as u64).rem_euclid(MODULUS)) }
            }
        }
    )* }
}
impl_from_unsigned_for_modp!(u8 u16 u32 u64 usize);
impl From<i128> for ModP {
    fn from(num: i128) -> ModP {
        unsafe { ModP::new_unchecked(num.rem_euclid(MODULUS as i128) as u64) }
    }
}
impl From<u128> for ModP {
    fn from(num: u128) -> ModP {
        unsafe { ModP::new_unchecked(num.rem_euclid(MODULUS as u128) as u64) }
    }
}
impl std::ops::Add for ModP {
    type Output = ModP;
    fn add(self, rhs: ModP) -> ModP {
        let m = unsafe { MODULUS };
        ModP { base: (self.base() + rhs.base() % m) % m }
    }
}
impl std::ops::Add<ModPBase> for ModP {
    type Output = ModP;
    fn add(self, rhs: ModPBase) -> ModP {
        self + ModP::new(rhs)
    }
}
impl std::ops::Add<ModP> for ModPBase {
    type Output = ModP;
    fn add(self, rhs: ModP) -> ModP {
        ModP::new(self) + rhs.base()
    }
}
impl std::ops::AddAssign for ModP {
    fn add_assign(&mut self, rhs: ModP) {
        *self = *self + rhs
    }
}
impl std::ops::AddAssign<ModPBase> for ModP {
    fn add_assign(&mut self, rhs: ModPBase) {
        *self = *self + ModP::new(rhs)
    }
}
impl std::ops::Neg for ModP {
    type Output = ModP;
    fn neg(self) -> ModP {
        ModP::new(unsafe { MODULUS } - self.base())
    }
}
impl std::ops::Sub for ModP {
    type Output = ModP;
    fn sub(self, rhs: ModP) -> ModP {
        self + (-rhs)
    }
}
impl std::ops::Sub<ModPBase> for ModP {
    type Output = ModP;
    fn sub(self, rhs: ModPBase) -> ModP {
        self - ModP::new(rhs)
    }
}
impl std::ops::Sub<ModP> for ModPBase {
    type Output = ModP;
    fn sub(self, rhs: ModP) -> ModP {
        ModP::new(self) - rhs
    }
}
impl std::ops::SubAssign for ModP {
    fn sub_assign(&mut self, rhs: ModP) {
        *self = *self - rhs;
    }
}
impl std::ops::SubAssign<ModPBase> for ModP {
    fn sub_assign(&mut self, rhs: ModPBase) {
        *self = *self - ModP::new(rhs)
    }
}
impl std::ops::Mul for ModP {
    type Output = ModP;
    fn mul(self, rhs: ModP) -> ModP {
        let m = unsafe { MODULUS };
        ModP { base: self.base() * (rhs.base() % m) % m }
    }
}
impl std::ops::Mul<ModPBase> for ModP {
    type Output = ModP;
    fn mul(self, rhs: ModPBase) -> ModP {
        self * ModP::new(rhs)
    }
}
impl std::ops::Mul<ModP> for ModPBase {
    type Output = ModP;
    fn mul(self, rhs: ModP) -> ModP {
        ModP::new(self) * rhs.base()
    }
}
impl std::ops::MulAssign for ModP {
    fn mul_assign(&mut self, rhs: ModP) {
        *self = *self * rhs
    }
}
impl std::ops::MulAssign<ModPBase> for ModP {
    fn mul_assign(&mut self, rhs: ModPBase) {
        *self = *self * ModP::new(rhs)
    }
}
impl std::ops::Div for ModP {
    type Output = ModP;
    fn div(self, rhs: ModP) -> ModP {
        self * rhs.inv()
    }
}
impl std::ops::Div<ModPBase> for ModP {
    type Output = ModP;
    fn div(self, rhs: ModPBase) -> ModP {
        self * ModP::new(rhs).inv()
    }
}
impl std::ops::Div<ModP> for ModPBase {
    type Output = ModP;
    fn div(self, rhs: ModP) -> ModP {
        ModP::new(self) * rhs.inv()
    }
}
impl std::ops::DivAssign for ModP {
    fn div_assign(&mut self, rhs: ModP) {
        *self = *self / rhs;
    }
}
impl std::ops::DivAssign<ModPBase> for ModP {
    fn div_assign(&mut self, rhs: ModPBase) {
        *self = *self / ModP::new(rhs)
    }
}
forward_ref_binop!(impl Add, add for ModP, ModP);
forward_ref_binop!(impl Add, add for ModP, ModPBase);
forward_ref_binop!(impl Add, add for ModPBase, ModP);
forward_ref_op_assign!(impl AddAssign, add_assign for ModP, ModP);
forward_ref_op_assign!(impl AddAssign, add_assign for ModP, ModPBase);
forward_ref_unop!(impl Neg, neg for ModP);
forward_ref_binop!(impl Sub, sub for ModP, ModP);
forward_ref_binop!(impl Sub, sub for ModP, ModPBase);
forward_ref_binop!(impl Sub, sub for ModPBase, ModP);
forward_ref_op_assign!(impl SubAssign, sub_assign for ModP, ModP);
forward_ref_op_assign!(impl SubAssign, sub_assign for ModP, ModPBase);
forward_ref_binop!(impl Mul, mul for ModP, ModP);
forward_ref_binop!(impl Mul, mul for ModP, ModPBase);
forward_ref_binop!(impl Mul, mul for ModPBase, ModP);
forward_ref_op_assign!(impl MulAssign, mul_assign for ModP, ModP);
forward_ref_op_assign!(impl MulAssign, mul_assign for ModP, ModPBase);
forward_ref_binop!(impl Div, div for ModP, ModP);
forward_ref_binop!(impl Div, div for ModP, ModPBase);
forward_ref_binop!(impl Div, div for ModPBase, ModP);
forward_ref_op_assign!(impl DivAssign, div_assign for ModP, ModP);
forward_ref_op_assign!(impl DivAssign, div_assign for ModP, ModPBase);
impl std::iter::Sum for ModP {
    fn sum<I: Iterator<Item=ModP>>(iter: I) -> ModP {
        let mut ans = 0;
        for n in iter {
            ans += n.base();
        }
        ModP::new(ans)
    }
}
impl<'a> std::iter::Sum<&'a ModP> for ModP {
    fn sum<I: Iterator<Item=&'a ModP>>(iter: I) -> ModP {
        let mut ans = 0;
        for n in iter {
            ans += n.base();
        }
        ModP::new(ans)
    }
}
impl std::iter::Product for ModP {
    fn product<I: Iterator<Item=ModP>>(iter: I) -> ModP {
        let mut ans = unsafe { ModP::new_unchecked(1) };
        for n in iter {
            ans *= n;
        }
        ans
    }
}
impl<'a> std::iter::Product<&'a ModP> for ModP {
    fn product<I: Iterator<Item=&'a ModP>>(iter: I) -> ModP {
        let mut ans = unsafe { ModP::new_unchecked(1) };
        for &n in iter {
            ans *= n;
        }
        ans
    }
}
readable!(ModP, 1, |ws| ModP::new(ws[0].read::<ModPBase>()));
pub struct FactCache {
    table: Vec<ModP>
}
impl FactCache {
    pub fn get(&mut self, n: ModPBase) -> ModP {
        self.extend(n as usize);
        self.table[n as usize]
    }
    fn extend(&mut self, max: usize) {
        for i in self.table.len()..max+1 {
            let prev = self.table[i-1];
            self.table.push(prev * i as ModPBase);
        }
    }
}
pub struct InvCache {
    table: Vec<ModP>
}
impl InvCache {
    pub fn get(&mut self, n: ModPBase) -> ModP {
        assert!(n > 0);
        self.extend(n as usize);
        self.table[n as usize]
    }
    fn extend(&mut self, max: usize) {
        for i in self.table.len()..max+1 {
            let m = unsafe { MODULUS };
            let prev = self.table[m as usize % i];
            self.table.push(m / i as ModPBase * (-prev));
        }
    }
}
pub struct PowCache {
    base: ModPBase,
    table: Vec<ModP>
}
impl PowCache {
    pub fn get(&mut self, n: ModPBase) -> ModP {
        self.extend(n as usize);
        self.table[n as usize]
    }
    fn extend(&mut self, max: usize) {
        for i in self.table.len()..max+1 {
            let prev = self.table[i-1];
            self.table.push(prev * self.base);
        }
    }
}
pub struct CombinatoricsCache {
    facts: FactCache,
    invs: InvCache,
    finvs: Vec<ModP>,
}
impl CombinatoricsCache {
    pub fn choose(&mut self, n: ModPBase, m: ModPBase) -> ModP {
        if n < m {
            return ModP::new(0);
        }
        self.extend_finvs(std::cmp::max(m, n-m) as usize);
        self.fact(n) * self.finvs[m as usize] * self.finvs[(n-m) as usize]
    }
    pub fn permutation(&mut self, n: ModPBase, m: ModPBase) -> ModP {
        if n < m {
            return ModP::new(0);
        }
        self.extend_finvs((n-m) as usize);
        self.fact(n) * self.finvs[(n-m) as usize]
    }
    pub fn multichoose(&mut self, n: ModPBase, m: ModPBase) -> ModP {
        if m == 0 {
            ModP::new(1)
        } else {
            self.choose(n+m-1, m)
        }
    }
    pub fn c(&mut self, n: ModPBase, m: ModPBase) -> ModP {
        self.choose(n, m)
    }
    pub fn p(&mut self, n: ModPBase, m: ModPBase) -> ModP {
        self.permutation(n, m)
    }
    pub fn h(&mut self, n: ModPBase, m: ModPBase) -> ModP {
        self.multichoose(n, m)
    }
    pub fn fact(&mut self, n: ModPBase) -> ModP {
        self.facts.get(n)
    }
    pub fn inv(&mut self, n: ModPBase) -> ModP {
        self.invs.get(n)
    }
    fn extend_finvs(&mut self, max: usize) {
        for i in self.finvs.len()..max+1 {
            let prev = self.finvs[i-1];
            self.finvs.push(prev * self.invs.get(i as ModPBase))
        }
    }
}

// SNIPPET cmp
use std::cmp::{Ord, Ordering};
pub fn minmax<T: Ord>(a: T, b: T) -> (T, T) {
    if a <= b { (a, b) } else { (b, a) }
}
#[macro_export]
macro_rules! chmin {
    ($place: expr, $expr: expr) => {
        let value = $expr;
        if value < $place {
            $place = value;
        }
    }
}
#[macro_export]
macro_rules! chmax {
    ($place: expr, $expr: expr) => {
        let value = $expr;
        if value > $place {
            $place = value;
        }
    }
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Hash)]
pub struct Reverse<T: Ord>(pub T);
impl<T: Ord> PartialOrd for Reverse<T> {
    fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}
impl<T: Ord> Ord for Reverse<T> {
    fn cmp(&self, other: &Reverse<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}
pub trait SortDesc<T> {
    fn sort_desc(&mut self) where T: Ord;
    fn sort_desc_by<F>(&mut self, cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering;
    fn sort_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, key: F);
    fn sort_unstable_desc(&mut self) where T: Ord;
    fn sort_unstable_desc_by<F>(&mut self, cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering;
    fn sort_unstable_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, key: F);
}
impl<T> SortDesc<T> for [T] {
    fn sort_desc(&mut self) where T: Ord {
        self.sort_by(|x, y| y.cmp(x));
    }
    fn sort_desc_by<F>(&mut self, mut cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering
    {
        self.sort_by(|x, y| cmp(y, x));
    }
    fn sort_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, mut key: F) {
        self.sort_by_key(|x| Reverse(key(x)));
    }
    fn sort_unstable_desc(&mut self) where T: Ord {
        self.sort_unstable_by(|x, y| y.cmp(x));
    }
    fn sort_unstable_desc_by<F>(&mut self, mut cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering
    {
        self.sort_unstable_by(|x, y| cmp(y, x));
    }
    fn sort_unstable_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, mut key: F) {
        self.sort_unstable_by_key(|x| Reverse(key(x)));
    }
}
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default, Hash)]
pub struct Total<T: PartialOrd + PartialEq>(pub T);
impl<T: PartialOrd + PartialEq> Eq for Total<T> {}
impl<T: PartialOrd + PartialEq> Ord for Total<T> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}
pub trait IteratorMinmax: Iterator {
    fn minmax(self) -> Option<(Self::Item, Self::Item)>;
    fn minmax_by_key<K, F>(self, key_fn: F) -> Option<(Self::Item, Self::Item)>
    where
        K: Ord,
        F: FnMut(&Self::Item) -> K;
    fn minmax_by<F>(self, compare: F) -> Option<(Self::Item, Self::Item)>
    where
        F: FnMut(&Self::Item, &Self::Item) -> Ordering;
}
impl<T: Ord + Clone, I: Iterator<Item=T>> IteratorMinmax for I {
    fn minmax(self) -> Option<(Self::Item, Self::Item)> {
        self.minmax_by(|a, b| a.cmp(b))
    }
    fn minmax_by_key<K, F>(self, mut key_fn: F) -> Option<(Self::Item, Self::Item)>
    where
        K: Ord,
        F: FnMut(&Self::Item) -> K
    {
        self.minmax_by(|a, b| key_fn(a).cmp(&key_fn(b)))
    }
    fn minmax_by<F>(mut self, mut compare: F) -> Option<(Self::Item, Self::Item)>
    where
        F: FnMut(&Self::Item, &Self::Item) -> Ordering
    {
        let first = self.next()?;
        let second = match self.next() {
            Some(x) => x,
            None => return Some((first.clone(), first))
        };
        let mut result = minmax(first, second);
        while let Some(x) = self.next() {
            let (min, max) = result;
            result = if compare(&x, &min) == Ordering::Less {
                (x, max)
            } else if compare(&max, &x) == Ordering::Less {
                (min, x)
            } else {
                (min, max)
            };
        }
        Some(result)
    }
}
pub trait WithCmpIdentity<T>: Sized {
    fn new(x: T) -> Self;
    fn inf() -> Self;
    fn as_option(&self) -> Option<&T>;
    fn as_option_mut(&mut self) -> Option<&mut T>;
    fn into_option(self) -> Option<T>;
    fn is_fin(&self) -> bool {
        self.as_option().is_some()
    }
    fn is_inf(&self) -> bool {
        self.as_option().is_none()
    }
    fn expect_fin(self, msg: &str) -> T {
        self.into_option().expect(msg)
    }
    fn fin(self) -> T {
        self.into_option().unwrap()
    }
    fn fin_or(self, default: T) -> T {
        self.into_option().unwrap_or(default)
    }
    fn fin_or_else<F: FnOnce() -> T>(self, f: F) -> T {
        self.into_option().unwrap_or_else(f)
    }
    fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
        self.into_option().map_or(default, f)
    }
    fn map_or_else<U, D, F>(self, default: D, f: F) -> U
    where
        D: FnOnce() -> U,
        F: FnOnce(T) -> U
    {
        self.into_option().map_or_else(default, f).into()
    }
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum MaybeNegInf<T> {
    Inf,
    Fin(T)
}
pub type Max<T> = MaybeNegInf<T>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum MaybeInf<T> {
    Fin(T),
    Inf
}
pub type Min<T> = MaybeInf<T>;
macro_rules! impl_with_cmp_identity {
    ($t:ident) => {
        impl<T> $t<T> {
            pub fn map<U: Ord, F: FnOnce(T) -> U>(self, f: F) -> $t<U> {
                match self {
                    $t::Fin(x) => $t::Fin(f(x)),
                    $t::Inf => $t::Inf
                }
            }
        }
        impl<T> WithCmpIdentity<T> for $t<T> {
            fn new(x: T) -> $t<T> { $t::Fin(x) }
            fn inf() -> $t<T> { $t::Inf }
            fn as_option(&self) -> Option<&T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
            fn as_option_mut(&mut self) -> Option<&mut T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
            fn into_option(self) -> Option<T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
        }
    }
}
impl_with_cmp_identity!(MaybeNegInf);
impl_with_cmp_identity!(MaybeInf);

// END SNIPPETS
// Here is the documentation: https://yoshrc.github.io/rust-atcoder-snippets/atcoder_snippets/index.html

fn main() {
    unsafe { ModP::set_mod(1_000_000_007).unwrap(); }
    read!(n = usize, k = usize);
    read!(aa = Vec<i64>);

    let ans = if n == k {
        aa
    } else {
        let mut positives: Vec<_> = aa.iter().copied().filter(|&a| a > 0).collect();
        let mut nonposs: Vec<_> = aa.iter().copied().filter(|&a| a <= 0).collect();
        if positives.is_empty() {
            if k % 2 == 0 {
                nonposs.sort();
            } else {
                nonposs.sort_desc();
            }
            nonposs.truncate(k);
            nonposs
        } else {
            positives.sort_desc();
            nonposs.sort();
            let mut ans = Vec::new();
            let mut i_p = 0;
            let mut i_n = 0;
            if k % 2 == 1 {
                ans.push(positives[0]);
                i_p += 1;
            }
            while i_p + i_n < k {
                match (positives.get(i_p..i_p+2), nonposs.get(i_n..i_n+2)) {
                    (Some(ps), Some(ns)) => {
                        let p = ps[0] * ps[1];
                        let n = ns[0] * ns[1];
                        if p >= n {
                            ans.extend_from_slice(ps);
                            i_p += 2;
                        } else {
                            ans.extend_from_slice(ns);
                            i_n += 2;
                        }
                    },
                    (Some(ps), None) => {
                        ans.extend_from_slice(ps);
                        i_p += 2;
                    },
                    (None, Some(ns)) => {
                        ans.extend_from_slice(ns);
                        i_n += 2;
                    },
                    _ => panic!()
                }
            }
            ans
        }
    };

    echo!(ans.into_iter().map(|x| ModP::from(x)).product::<ModP>());
}