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

#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

/*
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx,avx2,fma")
*/

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                      { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
int dc[] = {+0, +0, +1, -1};
//int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
//int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

//#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct mi {
      long long v;
      explicit operator long long() const { return v; }
      mi() { v = 0; }
      mi(long long _v) { v = (-MOD < _v && _v < MOD) ? _v : _v % MOD; if (v < 0) { v += MOD; } }

      friend bool operator == (const mi& a, const mi& b) { return a.v == b.v; }
      friend bool operator != (const mi& a, const mi& b) { return !(a == b); }
      friend bool operator < (const mi& a, const mi& b) { return a.v < b.v; }

      mi& operator += (const mi& m) { if ((v += m.v) >= MOD) { v -= MOD; } return *this; }
      mi& operator -= (const mi& m) { if ((v -= m.v) < 0) { v += MOD; } return *this; }
      mi& operator *= (const mi& m) { v = v * m.v % MOD; return *this; }
      mi& operator /= (const mi& m) { return (*this) *= inv(m); }

      friend mi pow(mi a, long long p) { mi ans = 1; assert(p >= 0); for (; p; p /= 2, a *= a) { if (p & 1) { ans *= a; } } return ans; }
      friend mi inv(const mi& a)       { assert(a.v != 0); return pow(a, MOD - 2); }

      mi operator - () const { return mi(-v); }
      mi& operator ++ () { return *this += 1; }
      mi& operator -- () { return *this -= 1; }
      mi operator ++ (int) { mi temp; temp.v = v++; return temp; }
      mi operator -- (int) { mi temp; temp.v = v--; return temp; }

      friend mi operator + (mi a, const mi& b) { return a += b; }
      friend mi operator - (mi a, const mi& b) { return a -= b; }
      friend mi operator * (mi a, const mi& b) { return a *= b; }
      friend mi operator / (mi a, const mi& b) { return a /= b; }

      friend ostream& operator << (ostream& os, const mi& m) { os << m.v; return os; }
      friend istream& operator >> (istream& is, mi& m) { long long x; is >> x; m.v = x; return is; }
};

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);


      int n, k;
      cin >> n >> k;
      vector <ll> pos;
      vector <ll> neg;
      for (int i = 0; i < n; i++) {
            ll x;
            cin >> x;
            if (x >= 0) {
                  pos.push_back(x);
            }
            else {
                  neg.push_back(x);
            }
      }
      sort(rall(pos));
      sort(all(neg));
      if (pos.size() == 0) {
            reverse(all(neg));
            mi ans = 1;
            for (int i = 0; i < k; i++) {
                  ans *= neg[i];
            }
            cout << ans << endl;
            return 0;
      }
      if (n == k) {
            mi ans = 1;
            for (ll x : neg) {
                  ans *= x;
            }
            for (ll y : pos) {
                  ans *= y;
            }
            cout << ans << endl;
            return 0;
      }
      int myk = k;
      while (pos.size() > k) {
            pos.pop_back();
      }
      while (neg.size() > k) {
            neg.pop_back();
      }
      reverse(all(neg));
//      debug(myk, k, pos, neg);
      vector <ll> takeNeg;
      vector <ll> takePos;
      while (neg.size() > 1 and pos.size() > 1) {
            ll a = neg.back(); neg.pop_back();
            ll b = neg.back(); neg.pop_back();
            ll mul = a * b;
            int extra = k - (takeNeg.size() + 2);
            if (extra > pos.size()) {
                  takeNeg.push_back(a);
                  takeNeg.push_back(b);
                  continue;
            }
            ll aa = pos.back(); pos.pop_back();
            ll bb = pos.back(); pos.pop_back();
            ll mul2 = aa * bb;
//            debug(a, b, mul, aa, bb, mul2);
            if (mul >= mul2) {
                  takeNeg.push_back(a);
                  takeNeg.push_back(b);
            }
            else {
                  pos.push_back(aa);
                  pos.push_back(bb);
                  break;
            }
      }
      mi ans = 1;
//      debug("OK", takeNeg, pos);
      assert(takeNeg.size() + pos.size() == myk);
      for (ll x : takeNeg) {
            ans *= x;
      }
      for (ll x : pos) {
            ans *= x;
      }
      cout << ans << endl;



      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}