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)

#![allow(unused_imports)]
#![allow(unused_macros)]
use std::cmp::{max, min};
use std::collections::*;
use std::io::{stdin, Read};

use std::fmt::Display;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
use std::str::FromStr;
pub const MOD: usize = 1000_000_007;

#[derive(Clone, Copy, PartialEq, Debug, Default)]
pub struct Mint<T>(pub T);

impl Mint<usize> {
    pub fn pow(self, exp: usize) -> Self {
        let mut exp = exp;
        let mut v = self;
        let mut ret = Mint(1);
        while exp > 0 {
            if exp & 1 == 1 {
                ret *= v;
            }
            v *= v;
            exp >>= 1;
        }
        ret
    }
    pub fn inv(self) -> Self {
        self.pow(MOD - 2)
    }
}

impl<T: Display + Copy + PartialEq> Display for Mint<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl<T: FromStr + Copy + PartialEq> FromStr for Mint<T> {
    type Err = T::Err;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let v = T::from_str(s)?;
        Ok(Mint(v))
    }
}

impl Add<usize> for Mint<usize> {
    type Output = Self;
    fn add(self, rhs: usize) -> Self::Output {
        Mint((self.0 + rhs) % MOD)
    }
}

impl Add for Mint<usize> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        self + rhs.0
    }
}

impl AddAssign<usize> for Mint<usize> {
    fn add_assign(&mut self, rhs: usize) {
        *self = *self + rhs;
    }
}

impl AddAssign for Mint<usize> {
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs;
    }
}

impl Sub<usize> for Mint<usize> {
    type Output = Self;
    fn sub(self, rhs: usize) -> Self::Output {
        let rhs = rhs % MOD;
        let lhs = self.0 + if self.0 < rhs { MOD } else { 0 };
        Mint(lhs - rhs)
    }
}

impl Sub for Mint<usize> {
    type Output = Self;
    fn sub(self, rhs: Self) -> Self::Output {
        self - rhs.0
    }
}

impl SubAssign<usize> for Mint<usize> {
    fn sub_assign(&mut self, rhs: usize) {
        *self = *self - rhs
    }
}

impl SubAssign for Mint<usize> {
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs
    }
}

impl Mul<usize> for Mint<usize> {
    type Output = Self;
    fn mul(self, rhs: usize) -> Self::Output {
        Mint((self.0 * rhs) % MOD)
    }
}

impl Mul for Mint<usize> {
    type Output = Self;
    fn mul(self, rhs: Self) -> Self::Output {
        self * rhs.0
    }
}

impl MulAssign<usize> for Mint<usize> {
    fn mul_assign(&mut self, rhs: usize) {
        *self = *self * rhs;
    }
}

impl MulAssign for Mint<usize> {
    fn mul_assign(&mut self, rhs: Self) {
        *self = *self * rhs;
    }
}

impl Div<usize> for Mint<usize> {
    type Output = Self;
    fn div(self, rhs: usize) -> Self::Output {
        self * Mint(rhs).pow(MOD - 2)
    }
}

impl Div for Mint<usize> {
    type Output = Self;
    fn div(self, rhs: Self) -> Self::Output {
        self / rhs.0
    }
}

impl DivAssign<usize> for Mint<usize> {
    fn div_assign(&mut self, rhs: usize) {
        *self = *self / rhs;
    }
}
impl DivAssign for Mint<usize> {
    fn div_assign(&mut self, rhs: Self) {
        *self = *self / rhs;
    }
}

#[allow(unused_macros)]
macro_rules! parse {
    ($it: ident ) => {};
    ($it: ident, ) => {};
    ($it: ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
}

#[allow(unused_macros)]
macro_rules! parse_val {
    ($it: ident, [$t:tt; $len:expr]) => {
        (0..$len).map(|_| parse_val!($it, $t)).collect::<Vec<_>>();
    };
    ($it: ident, ($($t: tt),*)) => {
        ($(parse_val!($it, $t)),*)
    };
    ($it: ident, u1) => {
        $it.next().unwrap().parse::<usize>().unwrap() -1
    };
    ($it: ident, $t: ty) => {
        $it.next().unwrap().parse::<$t>().unwrap()
    };
}

#[cfg(debug_assertions)]
macro_rules! debug {
    ($( $args:expr ),*) => { eprintln!( $( $args ),* ); }
}

#[cfg(not(debug_assertions))]
macro_rules! debug {
    ($( $args:expr ),*) => {
        ()
    };
}

fn solve(s: &str) {
    let mut it = s.split_whitespace();
    parse!(it, n: usize, k: usize, a: [i64; n]);
    let a: Vec<i64> = a;
    // 0を選ばなきゃいけないときは0
    let numzero = a.iter().filter(|&&x| x == 0).count();
    if k + numzero > n {
        println!("{}", 0);
        return;
    }
    // 0を取り除く
    let a: Vec<i64> = a.iter().filter(|&&x| x != 0).map(|x| *x).collect();
    let n = a.len();

    // usize, signのタプルに変換
    let mut a: Vec<(usize, bool)> = a.iter().map(|&x| (x.abs() as usize, x >= 0)).collect();
    // 基本的には大きい方から見ていく
    a.sort();
    a.reverse();

    // 全部負かつkが奇数なら積はマイナスとなるから最も絶対値の小さいやつを選ぶ
    if a.iter().all(|(x, s)| !s) && k % 2 == 1 {
        if numzero > 0 {
            println!("{}", 0);
            return;
        }
        let mut ret = Mint(1);
        for &(ai, _) in a.iter().rev().take(k) {
            ret *= Mint(ai);
        }
        println!("{}", MOD - ret.0);
        return;
    }

    // 全部選ぶ場合
    if n == k {
        let mut ret = Mint(1);
        let mut isminus = false;
        for &(ai, s) in a.iter() {
            ret *= Mint(ai);
            if !s {
                isminus = !isminus;
            }
        }
        if isminus {
            if numzero > 0 {
                println!("{}", 0);
            } else {
                println!("{}", MOD - ret.0);
            }
        } else {
            println!("{}", ret);
        }
        return;
    }

    let mut ret = Mint(1);
    let mut isminus = false;
    let mut lf = None;
    let mut lt = None;
    let mut count = 0;
    for &(ai, s) in a.iter() {
        ret *= Mint(ai);
        if s {
            lt = Some(ai);
        } else {
            lf = Some(ai);
            isminus = !isminus;
        }
        count += 1;
        if count == k {
            break;
        }
    }
    if isminus {
        let lf = lf.unwrap();
        let mut nf = None;
        let mut nt = None;
        // 選んでないもののうちから絶対値が大きい+,-の項を取る
        for &(ai, s) in a[count..].iter() {
            if s && nt == None {
                nt = Some(ai);
            } else if !s && nf == None {
                nf = Some(ai)
            }
        }

        if let Some(lt) = lt {
            match (nf, nt) {
                (None, None) => unreachable!(),
                (Some(nf), None) => {
                    ret /= Mint(lt);
                    ret *= Mint(nf);
                }
                (None, Some(nt)) => {
                    ret /= Mint(lf);
                    ret *= Mint(nt);
                }
                (Some(nf), Some(nt)) => {
                    if nt * lt < nf * lf {
                        ret /= Mint(lt);
                        ret *= Mint(nf)
                    } else {
                        ret /= Mint(lf);
                        ret *= Mint(nt);
                    }
                }
            }
        } else {
            let nt = nt.unwrap();
            ret /= Mint(lf);
            ret *= Mint(nt);
        }
    }
    println!("{}", ret);
}

fn main() {
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    solve(&s);
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_input() {
        let s = "
        ";
        solve(s);
    }
}