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: Runtime Error)

use proconio::input;

trait OrdTools: Ord + Clone + Sized {
    fn chmin(&mut self, x: Self) {
        *self = std::cmp::min(self.clone(), x);
    }
    fn chmax(&mut self, x: Self) {
        *self = std::cmp::max(self.clone(), x);
    }
}

impl<T: Ord + Clone + Sized> OrdTools for T {}

trait ModValue:
    std::ops::Add<Output = Self>
    + std::ops::Sub<Output = Self>
    + std::ops::Mul<Output = Self>
    + std::ops::Div<Output = Self>
    + std::ops::Rem<Output = Self>
    + std::ops::AddAssign
    + std::ops::SubAssign
    + std::ops::MulAssign
    + std::ops::DivAssign
    + std::ops::RemAssign
    + std::ops::Neg
    + std::cmp::Ord
    + Clone
    + Copy
    + std::fmt::Debug
    + Sized
{
    fn modulus() -> Self;
    fn zero() -> Self;
    fn one() -> Self;
}

#[derive(Clone, Copy, Debug)]
struct Modint<Value: ModValue>(Value);

impl<Value: ModValue> Modint<Value> {
    #[allow(dead_code)]
    pub fn with_value(x: Value) -> Self {
        Self(Self::normalize(x))
    }

    #[allow(dead_code)]
    pub fn with_value_unchecked(x: Value) -> Self {
        Self(x)
    }

    #[allow(dead_code)]
    pub fn validate(&self) -> &Self {
        assert!(Value::zero() <= self.0 && self.0 < Value::modulus());
        &self
    }

    fn normalize(x: Value) -> Value {
        let x = x % Value::modulus();
        if x < Value::zero() {
            x + Value::modulus()
        } else {
            x
        }
    }

    fn add_unchecked(x: Value, y: Value) -> Value {
        let z = x + y;
        if Value::modulus() <= z {
            z - Value::modulus()
        } else {
            z
        }
    }

    fn sub_unchecked(x: Value, y: Value) -> Value {
        let z = x - y;
        if x < Value::zero() {
            z + Value::modulus()
        } else {
            z
        }
    }

    fn neg_unchecked(x: Value) -> Value {
        if x == Value::zero() {
            Value::zero()
        } else {
            Value::modulus() - x
        }
    }

    fn mul_unchecked(x: Value, y: Value) -> Value {
        x * y % Value::modulus()
    }

    fn div_unchecked(x: Value, y: Value) -> Value {
        Self::mul_unchecked(x, Self::inv_unchecked(y))
    }

    fn inv_unchecked(mut x: Value) -> Value {
        let mut y: Value = Value::modulus();
        let mut u: Value = Value::one();
        let mut v: Value = Value::zero();
        while x != Value::zero() {
            let q = y / x;
            y -= x * q;
            v -= u * q;
            std::mem::swap(&mut x, &mut y);
            std::mem::swap(&mut u, &mut v);
        }
        if v < Value::zero() {
            v + Value::modulus()
        } else {
            v
        }
    }
}

macro_rules! impl_bop {
    (
        $(
            $bop_trait: ident::$bop_fn: ident, $bop_assign_trait: ident::$bop_assign_fn: ident, $impl: ident;
        )*
    ) => {
        $(
            impl<Value: ModValue> std::ops::$bop_trait for Modint<Value> {
                type Output = Self;
                fn $bop_fn(self, rhs: Self) -> Self::Output {
                    Modint(Self::$impl(self.0, rhs.0))
                }
            }
            impl<Value: ModValue> std::ops::$bop_assign_trait for Modint<Value> {
                fn $bop_assign_fn(&mut self, rhs: Self) {
                    use std::ops::$bop_trait;
                    *self = Modint::$bop_fn(*self, rhs)
                }
            }
        )*
    };
}

impl_bop! {
    Add::add, AddAssign::add_assign, add_unchecked;
    Sub::sub, SubAssign::sub_assign, sub_unchecked;
    Mul::mul, MulAssign::mul_assign, mul_unchecked;
    Div::div, DivAssign::div_assign, div_unchecked;
}

impl<Value: ModValue> std::ops::Neg for Modint<Value> {
    type Output = Self;
    fn neg(self) -> Self::Output {
        Modint(Self::neg_unchecked(self.0))
    }
}

impl<Value: ModValue> std::iter::Sum<Self> for Modint<Value> {
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Self::with_value(Value::zero()), std::ops::Add::add)
    }
}

impl<Value: ModValue> std::iter::Product<Self> for Modint<Value> {
    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Self::with_value(Value::one()), std::ops::Mul::mul)
    }
}

impl<Value: ModValue> std::convert::From<Value> for Modint<Value> {
    fn from(x: Value) -> Self {
        Self::with_value(x)
    }
}

#[allow(unused_macros)]
macro_rules! modint {
    ($x: expr) => {
        Modint::with_value($x)
    };
}

#[allow(unused_macros)]
macro_rules! impl_modvalue {
    ($(const $mod_name: ident: $ty: ty = $mod_value: expr;)*) => {
        $(
            const $mod_name: $ty = $mod_value;
            impl ModValue for $ty {
                fn modulus() -> Self {
                    $mod_name
                }
                fn zero() -> Self {
                    0
                }
                fn one() -> Self {
                    1
                }
            }
        )*
    };
}

impl_modvalue! {const MOD: i64= 1_000_000_007;}

fn main() {
    input!(n: usize, k: usize, mut a: [i64; n]);
    a.sort_by_key(|&x| std::cmp::Reverse(x));
    let ans: Modint<i64> = if n == k {
        a.iter().map(|&x| modint!(x)).product()
    } else if k % 2 == 1 && a.iter().all(|&x| x < 0) {
        a[0..k].iter().map(|&x| modint!(x)).product()
    } else {
        let mut b = vec![];
        if k % 2 == 1 {
            b.push(a[0]);
        }
        let p = a.iter().take_while(|&&x| 0 < x).count();
        let q = a.iter().take_while(|&&x| 0 <= x).count();
        for sub in a[k % 2..p].chunks(2) {
            b.push(sub[0] * sub[1]);
        }
        for sub in a[(if (n - q) % 2 == 0 { q } else { q + 1 })..n].chunks(2) {
            b.push(sub[0] * sub[1]);
        }
        b.sort_by_key(|&x| std::cmp::Reverse(x));
        b[0..(k + 1) / 2].iter().map(|&x| modint!(x)).product()
    };
    println!("{}", ans.0);
}