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)]
use {
   proconio::{fastout, input, marker::*},
   std::cmp::*,
   std::collections::*,
};

#[fastout]
fn main() {
   input! {
      n: usize,
      k: usize,
      mut a: [i64; n]
   }

   if n == k {
      let mut ans = Mint::new(1);
      for i in 0..k {
         ans *= a[i];
      }
      println!("{}", ans);
      return;
   }

   let mut pos = vec![];
   let mut neg = vec![];
   for &a in a.iter() {
      if a >= 0 {
         pos.push(a);
      } else {
         neg.push(-a);
      }
   }

   if pos.len() == 0 {
      if k % 2 == 1 {
         neg.sort();
      } else {
         neg.sort_by(|a, b| b.cmp(a));
      }
      let mut ans = Mint::new(1);
      for i in 0..k {
         ans *= -neg[i];
      }
      println!("{}", ans);
      return;
   }

   if neg.len() == 0 {
      pos.sort_by(|a, b| b.cmp(a));
      let mut ans = Mint::new(1);
      for i in 0..k {
         ans *= pos[i];
      }
      println!("{}", ans);
      return;
   }

   a.sort_by_key(|&a| -a.abs());
   let mut p1 = n;
   let mut n1 = n;
   let mut p2 = n;
   let mut n2 = n;
   let mut par = 0;
   for i in 0..k {
      if a[i] >= 0 {
         p1 = i;
      } else {
         n1 = i;
         par += 1;
      }
   }
   if par % 2 == 1 {
      for i in k..n {
         if a[i] >= 0 {
            p2 = i;
            break;
         }
      }
      for i in k..n {
         if a[i] < 0 {
            n2 = i;
            break;
         }
      }
   }
   if (p1 == n || n2 == n) && (n1 == n || p2 == n) {
   } else if p1 == n || n2 == n {
      let temp = a[n1];
      a[n1] = a[p2];
      a[p2] = temp;
   } else if n1 == n || p2 == n {
      let temp = a[p1];
      a[p1] = a[n2];
      a[n2] = temp;
   } else {
      if a[n1] * a[n2] > a[p1] * a[p2] {
         let temp = a[p1];
         a[p1] = a[n2];
         a[n2] = temp;
      } else {
         let temp = a[n1];
         a[n1] = a[p2];
         a[p2] = temp;
      }
   }
   let mut ans = Mint::new(1);
   for i in 0..k {
      ans *= a[i];
   }
   println!("{}", ans);
}

const MOD: i64 = 1000000007;
#[derive(Copy, Clone)]
pub struct Mint {
   x: i64,
}
impl Mint {
   fn new(x: i64) -> Self {
      Mint {
         x: x.rem_euclid(MOD),
      }
   }
   fn pow(self, n: usize) -> Self {
      match n {
         0 => Mint::new(1),
         _ => {
            let mut a = self.pow(n >> 1);
            a *= a;
            if n & 1 == 1 {
               a *= self;
            }
            a
         }
      }
   }
   fn inv(self) -> Self { self.pow((MOD - 2) as usize) }
}
impl std::ops::Neg for Mint {
   type Output = Mint;
   fn neg(self) -> Self::Output { Self::new(-self.x) }
}
impl std::ops::AddAssign<Mint> for Mint {
   fn add_assign(&mut self, rhs: Self) {
      self.x += rhs.x;
      self.x %= MOD;
   }
}
impl std::ops::AddAssign<i64> for Mint {
   fn add_assign(&mut self, rhs: i64) { *self += Mint::new(rhs); }
}
impl std::ops::AddAssign<usize> for Mint {
   fn add_assign(&mut self, rhs: usize) { *self += Mint::new(rhs as i64); }
}
impl<T> std::ops::Add<T> for Mint
where
   Mint: std::ops::AddAssign<T>,
{
   type Output = Self;
   fn add(self, other: T) -> Self {
      let mut res = self;
      res += other;
      res
   }
}
impl std::ops::SubAssign<Mint> for Mint {
   fn sub_assign(&mut self, rhs: Self) {
      self.x -= rhs.x;
      if self.x < 0 {
         self.x += MOD;
      }
   }
}
impl std::ops::SubAssign<i64> for Mint {
   fn sub_assign(&mut self, rhs: i64) { *self -= Mint::new(rhs); }
}
impl std::ops::SubAssign<usize> for Mint {
   fn sub_assign(&mut self, rhs: usize) { *self -= Mint::new(rhs as i64); }
}
impl<T> std::ops::Sub<T> for Mint
where
   Mint: std::ops::SubAssign<T>,
{
   type Output = Self;
   fn sub(self, other: T) -> Self {
      let mut res = self;
      res -= other;
      res
   }
}
impl std::ops::MulAssign<Mint> for Mint {
   fn mul_assign(&mut self, rhs: Self) {
      self.x *= rhs.x;
      self.x %= MOD;
   }
}
impl std::ops::MulAssign<i64> for Mint {
   fn mul_assign(&mut self, rhs: i64) { *self *= Mint::new(rhs); }
}
impl std::ops::MulAssign<usize> for Mint {
   fn mul_assign(&mut self, rhs: usize) { *self *= Mint::new(rhs as i64); }
}
impl<T> std::ops::Mul<T> for Mint
where
   Mint: std::ops::MulAssign<T>,
{
   type Output = Self;
   fn mul(self, other: T) -> Self {
      let mut res = self;
      res *= other;
      res
   }
}
impl std::ops::DivAssign<Mint> for Mint {
   fn div_assign(&mut self, rhs: Self) { *self *= rhs.inv(); }
}
impl std::ops::DivAssign<i64> for Mint {
   fn div_assign(&mut self, rhs: i64) { *self /= Mint::new(rhs); }
}
impl std::ops::DivAssign<usize> for Mint {
   fn div_assign(&mut self, rhs: usize) { *self /= Mint::new(rhs as i64); }
}
impl<T> std::ops::Div<T> for Mint
where
   Mint: std::ops::DivAssign<T>,
{
   type Output = Self;
   fn div(self, other: T) -> Self {
      let mut res = self;
      res /= other;
      res
   }
}
impl<T> From<T> for Mint
where
   i64: From<T>,
{
   fn from(x: T) -> Mint { Mint::new(i64::from(x)) }
}
impl std::fmt::Display for Mint {
   fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.x) }
}
impl std::ops::Deref for Mint {
   type Target = i64;
   fn deref(&self) -> &Self::Target { &self.x }
}