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 C++ (GCC 9.2.1) (judge verdict: Accepted)

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

namespace mod {

template <class T, int M>
class MInt;

template <class T, int M>
MInt<T, M> Pow(const MInt<T, M> &base, T exp);

template <class T, int M>
MInt<T, M> Inv(const MInt<T, M> &n);

template <class T, int M>
class MInt {
  T n_;

 public:
  MInt() : n_(0) {}
  MInt(T n) : n_((n % M + M) % M) {}

  MInt &operator+=(const MInt &rhs) {
    n_ += rhs.n_;
    if (n_ >= M) {
      n_ -= M;
    }

    return *this;
  }

  MInt &operator-=(const MInt &rhs) {
    n_ += M - rhs.n_;
    if (n_ >= M) {
      n_ -= M;
    }

    return *this;
  }

  MInt &operator*=(const MInt &rhs) {
    n_ = n_ * rhs.n_ % M;
    return *this;
  }

  MInt &operator/=(const MInt &rhs) { return (*this) *= Inv(rhs); }

  T Get() { return n_; }
};

template <class T, int M>
MInt<T, M> operator-(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res -= rhs;
}

template <class T, int M>
MInt<T, M> operator+(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res += rhs;
}

template <class T, int M>
MInt<T, M> operator*(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res *= rhs;
}

template <class T, int M>
MInt<T, M> operator/(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res /= rhs;
}

template <class T, int M>
MInt<T, M> Pow(const MInt<T, M> &base, T exp) {
  if (exp == 0) {
    return 1;
  }

  auto a = Pow(base, exp / 2);
  a *= a;
  if (exp % 2 == 1) {
    a *= base;
  }

  return a;
}

template <class T, int M>
MInt<T, M> Inv(const MInt<T, M> &n) {
  return Pow(n, static_cast<T>(M - 2));
}
}  // namespace mod

const int md = 1e9 + 7;
using MInt = mod::MInt<long long, md>;

int main(int argc, const char *argv[]) {
  int n, k;
  cin >> n >> k;

  // 正数の数，負数の数
  vector<ll> va(n), vb, vc;
  for (int i = 0; i < n; ++i) {
    cin >> va[i];
    if (va[i] >= 0) {
      vb.push_back(va[i]);
    } else {
      vc.push_back(-va[i]);
    }
  }

  ll md = 1e9 + 7;

  // 負数しか作れない場合，絶対値が小さい順に選ぶ
  // * Aを全て選ぶかつ，負数要素が奇数個ある
  // * Aが全て奇数かつ，奇数個選ぶ
  if ((vc.size() == n && k % 2 == 1) || (n == k && vc.size() % 2 == 1)) {
    sort(va.begin(), va.end(), [](ll a, ll b) { return abs(a) < abs(b); });
    MInt ans = 1;
    for (int i = 0; i < k; ++i) {
      ans *= MInt(va[i]);
    }
    cout << ans.Get() << '\n';
    return 0;
  }

  sort(vb.begin(), vb.end(), greater<ll>());
  sort(vc.begin(), vc.end(), greater<ll>());

  vector<ll> vc2;
  for (int i = 0; i < vc.size() - vc.size() % 2; i += 2) {
    vc2.push_back(vc[i] * vc[i + 1]);
  }

  vector<ll> vd;
  int cur_b = 0, cur_c = 0;

  // kを偶数にしておく
  if (k % 2 == 1) {
    vd.push_back(vb[cur_b++]);
    k--;
  }

  // 必ず2個ずつ選べる
  while (k > 0) {
    // 要素が足りないのでどちらかしか選べない
    if (cur_c >= vc2.size()) {
      vd.push_back(vb[cur_b++]);
      vd.push_back(vb[cur_b++]);
      k -= 2;
      continue;
    }

    if (cur_b >= vb.size()) {
      vd.push_back(vc2[cur_c++]);
      k -= 2;
      continue;
    }

    // `vb` が2つ以上あるとき
    if (cur_b < vb.size() - 1) {
      if (vb[cur_b] * vb[cur_b + 1] >= vc2[cur_c]) {
        vd.push_back(vb[cur_b++]);
        vd.push_back(vb[cur_b++]);
        k -= 2;
      } else {
        vd.push_back(vc2[cur_c++]);
        k -= 2;
      }
      continue;
    }

    vd.push_back(vc2[cur_c]);
    cur_c++;
    k -= 2;
  }

  MInt ans = 1;
  for (int i = 0; i < vd.size(); ++i) {
    ans *= MInt(vd[i]);
  }

  cout << ans.Get() << '\n';
}