Problem p02616 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
using namespace std;

// template {{{
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize

#define sz(x) int((x).size())
#define all(x) (x).begin(), (x).end()

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto &a : x)

#define sort_by(x, y)                                                          \\
  sort(all(x), [&](const auto &a, const auto &b) { return y; })

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;

using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;

template <typename T> void ckmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void ckmax(T &a, const T &b) { a = max(a, b); }

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

namespace __input {
template <class T1, class T2> void re(pair<T1, T2> &p);
template <class T> void re(vector<T> &a);
template <class T, size_t SZ> void re(array<T, SZ> &a);

template <class T> void re(T &x) { cin >> x; }
void re(double &x) {
  string t;
  re(t);
  x = stod(t);
}
template <class Arg, class... Args> void re(Arg &first, Args &...rest) {
  re(first);
  re(rest...);
}

template <class T1, class T2> void re(pair<T1, T2> &p) { re(p.f, p.s); }
template <class T> void re(vector<T> &a) { F0R(i, sz(a)) re(a[i]); }
template <class T, size_t SZ> void re(array<T, SZ> &a) { F0R(i, SZ) re(a[i]); }
} // namespace __input
using namespace __input;

namespace __output {
template <class T1, class T2> void pr(const pair<T1, T2> &x);
template <class T, size_t SZ> void pr(const array<T, SZ> &x);
template <class T> void pr(const vector<T> &x);
template <class T> void pr(const set<T> &x);
template <class T1, class T2> void pr(const map<T1, T2> &x);

template <class T> void pr(const T &x) { cout << x; }
template <class Arg, class... Args>
void pr(const Arg &first, const Args &...rest) {
  pr(first);
  pr(rest...);
}

template <class T1, class T2> void pr(const pair<T1, T2> &x) {
  pr("{", x.f, ", ", x.s, "}");
}
template <class T, bool pretty = true> void prContain(const T &x) {
  if (pretty)
    pr("{");
  bool fst = 1;
  for (const auto &a : x)
    pr(!fst ? pretty ? ", " : " " : "", a), fst = 0;
  if (pretty)
    pr("}");
}
template <class T> void pc(const T &x) {
  prContain<T, false>(x);
  pr("\\n");
}
template <class T, size_t SZ> void pr(const array<T, SZ> &x) { prContain(x); }
template <class T> void pr(const vector<T> &x) { prContain(x); }
template <class T> void pr(const set<T> &x) { prContain(x); }
template <class T1, class T2> void pr(const map<T1, T2> &x) { prContain(x); }

void ps() { pr("\\n"); }
template <class Arg> void ps(const Arg &first) {
  pr(first);
  ps();
}
template <class Arg, class... Args>
void ps(const Arg &first, const Args &...rest) {
  pr(first, " ");
  ps(rest...);
}
} // namespace __output
using namespace __output;

#define TRACE(x) x
#define __pn(x) pr(#x, " = ")
#define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush

namespace __algorithm {
template <typename T> void dedup(vector<T> &v) {
  sort(all(v));
  v.erase(unique(all(v)), v.end());
}
template <typename T>
typename vector<T>::const_iterator find(const vector<T> &v, const T &x) {
  auto it = lower_bound(all(v), x);
  return it != v.end() && *it == x ? it : v.end();
}
template <typename T> size_t index(const vector<T> &v, const T &x) {
  auto it = find(v, x);
  assert(it != v.end() && *it == x);
  return it - v.begin();
}

template <typename T1, typename T2>
typename vector<pair<T1, T2>>::iterator
lower_bound(const vector<pair<T1, T2>> &v, const T1 &x) {
  return lower_bound(all(v), x,
                     [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
}
template <typename T1, typename T2>
typename vector<pair<T1, T2>>::iterator
upper_bound(const vector<pair<T1, T2>> &v, const T1 &x) {
  return upper_bound(all(v), x,
                     [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
}
} // namespace __algorithm
using namespace __algorithm;

struct __monostate {
  friend istream &operator>>(istream &is,
                             const __attribute__((unused)) __monostate &ms) {
    return is;
  }
  friend ostream &operator<<(ostream &os,
                             const __attribute__((unused)) __monostate &ms) {
    return os;
  }
} ms;

namespace __io {
void setIn(string s) { freopen(s.c_str(), "r", stdin); }
void setOut(string s) { freopen(s.c_str(), "w", stdout); }
void setIO(string s = "") {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << setprecision(15);
  if (sz(s)) {
    setIn(s + ".in"), setOut(s + ".out");
  }
}
} // namespace __io
using namespace __io;
// }}}

// modnum {{{
using v_t = int;
using vv_t = ll;
template <v_t MOD> struct modnum {
  v_t v;
  modnum() : v(0) {}
  modnum(vv_t _v) : v(_v % MOD) {
    if (v < 0)
      v += MOD;
  }
  explicit operator v_t() const { return v; }
  friend istream &operator>>(istream &i, modnum &n) {
    vv_t w;
    i >> w;
    n = modnum(w);
    return i;
  }
  friend ostream &operator<<(ostream &o, const modnum &n) { return o << n.v; }

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

  static unsigned fast_mod(uint64_t x, unsigned m = MOD) {
#if !defined(_WIN32) || defined(_WIN64)
    return x % m;
#endif
    // x must be less than 2^32 * m so that x / m fits in a 32-bit integer.
    unsigned x_high = x >> 32, x_low = (unsigned)x, quot, rem;
    asm("divl %4\\n" : "=a"(quot), "=d"(rem) : "d"(x_high), "a"(x_low), "r"(m));
    return rem;
  }

  modnum &operator+=(const modnum &o) {
    v += o.v;
    if (v >= MOD)
      v -= MOD;
    return *this;
  }
  modnum &operator-=(const modnum &o) {
    v -= o.v;
    if (v < 0)
      v += MOD;
    return *this;
  }
  modnum &operator*=(const modnum &o) {
    v = fast_mod(vv_t(v) * o.v);
    return *this;
  }
  modnum operator-() {
    modnum res;
    if (v)
      res.v = MOD - v;
    return res;
  }
  friend modnum operator+(const modnum &a, const modnum &b) {
    return modnum(a) += b;
  }
  friend modnum operator-(const modnum &a, const modnum &b) {
    return modnum(a) -= b;
  }
  friend modnum operator*(const modnum &a, const modnum &b) {
    return modnum(a) *= b;
  }

  modnum pow(vv_t e) const {
    if (e < 0)
      return 1 / this->pow(-e);
    if (e == 0)
      return 1;
    if (e & 1)
      return *this * this->pow(e - 1);
    return (*this * *this).pow(e / 2);
  }

  modnum inv() const {
    v_t g = MOD, x = 0, y = 1;
    for (v_t r = v; r != 0;) {
      v_t q = g / r;
      g %= r;
      swap(g, r);
      x -= q * y;
      swap(x, y);
    }

    assert(g == 1);
    assert(y == MOD || y == -MOD);
    return x < 0 ? x + MOD : x;
  }
  modnum &operator/=(const modnum &o) { return (*this) *= o.inv(); }
  friend modnum operator/(const modnum &a, const modnum &b) {
    return modnum(a) /= modnum(b);
  }

  static constexpr v_t totient() {
    v_t tot = MOD, tmp = MOD;
    for (v_t p = 2; p * p <= tmp; p++)
      if (tmp % p == 0) {
        tot = tot / p * (p - 1);
        while (tmp % p == 0)
          tmp /= p;
      }
    if (tmp > 1)
      tot = tot / tmp * (tmp - 1);
    return tot;
  }

  static v_t primitive_root() {
    if (MOD == 1)
      return 0;
    if (MOD == 2)
      return 1;

    v_t tot = totient(), tmp = tot;
    vi tot_pr;
    for (v_t p = 2; p * p <= tmp; p++)
      if (tot % p == 0) {
        tot_pr.push_back(p);
        while (tmp % p == 0)
          tmp /= p;
      }
    if (tmp > 1)
      tot_pr.push_back(tmp);

    for (v_t r = 2; r < MOD; r++)
      if (__gcd(r, MOD) == 1) {
        bool root = true;
        for (v_t p : tot_pr)
          root &= modnum(r).pow(tot / p) != 1;
        if (root)
          return r;
      }
    assert(false);
  }

  static modnum generator() {
    static modnum g = primitive_root();
    return g;
  }
  static v_t discrete_log(modnum v) {
    static const v_t M = ceil(sqrt(MOD));
    static unordered_map<v_t, v_t> table;
    if (table.empty()) {
      modnum e = 1;
      for (v_t i = 0; i < M; i++) {
        table[e.v] = i;
        e *= generator();
      }
    }
    static modnum f = generator().pow(totient() - M);

    for (v_t i = 0; i < M; i++) {
      if (table.count(v.v))
        return table[v.v] + i * M;
      v *= f;
    }
    assert(false);
  }

  static modnum unity_root(int deg) {
    assert(totient() % deg == 0);
    return generator().pow(totient() / deg);
  }

  static modnum unity_root(int deg, int pow) {
    static vector<modnum> table{0, 1};
    while (sz(table) <= deg) {
      modnum w = unity_root(sz(table));
      for (int i = sz(table) / 2, s = sz(table); i < s; i++) {
        table.push_back(table[i]);
        table.push_back(table[i] * w);
      }
    }
    return table[deg + (pow < 0 ? deg + pow : pow)];
  }

  static modnum factorial(int n) {
    static vector<modnum> fact = {1};
    assert(n >= 0);
    if (sz(fact) <= n) {
      int had = sz(fact);
      fact.resize(n + 1);
      for (int i = had; i <= n; i++)
        fact[i] = fact[i - 1] * i;
    }
    return fact[n];
  }
  static modnum inverse_factorial(int n) {
    static vector<modnum> finv = {1};
    assert(n >= 0);
    if (sz(finv) <= n) {
      int had = sz(finv);
      finv.resz(n + 1), finv[n] = factorial(n).inv();
      for (int i = n - 1; i >= had; i--)
        finv[i] = finv[i + 1] * (i + 1);
    }
    return finv[n];
  }

  static modnum small_inv(int n) {
    assert(n > 0);
    return factorial(n - 1) * inverse_factorial(n);
  }

  static modnum ncr(int n, int r) {
    if (r < 0 || n < r)
      return 0;
    return factorial(n) * inverse_factorial(r) * inverse_factorial(n - r);
  }
};
// }}}
using mn = modnum<int(1e9 + 7)>;
using vmn = vector<mn>;
using vvmn = vector<vmn>;

int main() {
  setIO();

  int N, K;
  re(N, K);
  vi a(N);
  re(a);

  int neg = 0, zero = 0, pos = 0;
  trav(elt, a) {
    if (elt < 0)
      neg++;
    else if (elt == 0)
      zero++;
    else
      pos++;
  }

  if (K <= neg + pos) {
    sort(all(a));

    vi negs(a.begin(), a.begin() + neg);

    vi poss(a.begin() + neg + zero, a.end());
    reverse(all(poss));

    mn ans = 1;

    int n = 0, p = 0;
    F0R(i, K) {
      int next_neg = n < neg ? negs[n] : 0;
      int next_pos = p < pos ? poss[p] : 0;
      if (abs(next_neg) > abs(next_pos)) {
        ans *= next_neg;
        n++;
      } else {
        ans *= next_pos;
        p++;
      }
    }

    // pd(ans, n, p, negs, poss);

    if (n & 1) { // drop a pos for a neg or a neg for a pos
      pll dp = {n < neg ? negs[n] : 0, p > 0 ? poss[p - 1] : INT_MAX};
      bool canp = dp.f != 0 && dp.s != INT_MAX;
      pll dn = {p < pos ? poss[p] : 0, n > 0 ? negs[n - 1] : INT_MAX};
      bool cann = dn.f != 0 && dn.s != INT_MAX;

      if (canp && (!cann || dp.f * dn.s >= dn.f * dp.s)) {
        ps(ans * dp.f / dp.s);
        return 0;
      } else if (cann) {
        ps(ans * dn.f / dn.s);
        return 0;
      }
    } else {
      ps(ans);
      return 0;
    }
  }

  if (zero)
    ps(0);
  else {
    mn ans = 1;
    sort(all(a), [&](int x, int y) { return abs(x) < abs(y); });
    F0R(i, K) ans *= a[i];
    ps(ans);
  }

  return 0;
}


Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

// template {{{
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize

#define sz(x) int((x).size())
#define all(x) (x).begin(), (x).end()

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto &a : x)

#define sort_by(x, y)                                                          \\
  sort(all(x), [&](const auto &a, const auto &b) { return y; })

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;

using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;

template <typename T> void ckmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void ckmax(T &a, const T &b) { a = max(a, b); }

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

namespace __input {
template <class T1, class T2> void re(pair<T1, T2> &p);
template <class T> void re(vector<T> &a);
template <class T, size_t SZ> void re(array<T, SZ> &a);

template <class T> void re(T &x) { cin >> x; }
void re(double &x) {
  string t;
  re(t);
  x = stod(t);
}
template <class Arg, class... Args> void re(Arg &first, Args &...rest) {
  re(first);
  re(rest...);
}

template <class T1, class T2> void re(pair<T1, T2> &p) { re(p.f, p.s); }
template <class T> void re(vector<T> &a) { F0R(i, sz(a)) re(a[i]); }
template <class T, size_t SZ> void re(array<T, SZ> &a) { F0R(i, SZ) re(a[i]); }
} // namespace __input
using namespace __input;

namespace __output {
template <class T1, class T2> void pr(const pair<T1, T2> &x);
template <class T, size_t SZ> void pr(const array<T, SZ> &x);
template <class T> void pr(const vector<T> &x);
template <class T> void pr(const set<T> &x);
template <class T1, class T2> void pr(const map<T1, T2> &x);

template <class T> void pr(const T &x) { cout << x; }
template <class Arg, class... Args>
void pr(const Arg &first, const Args &...rest) {
  pr(first);
  pr(rest...);
}

template <class T1, class T2> void pr(const pair<T1, T2> &x) {
  pr("{", x.f, ", ", x.s, "}");
}
template <class T, bool pretty = true> void prContain(const T &x) {
  if (pretty)
    pr("{");
  bool fst = 1;
  for (const auto &a : x)
    pr(!fst ? pretty ? ", " : " " : "", a), fst = 0;
  if (pretty)
    pr("}");
}
template <class T> void pc(const T &x) {
  prContain<T, false>(x);
  pr("\\n");
}
template <class T, size_t SZ> void pr(const array<T, SZ> &x) { prContain(x); }
template <class T> void pr(const vector<T> &x) { prContain(x); }
template <class T> void pr(const set<T> &x) { prContain(x); }
template <class T1, class T2> void pr(const map<T1, T2> &x) { prContain(x); }

void ps() { pr("\\n"); }
template <class Arg> void ps(const Arg &first) {
  pr(first);
  ps();
}
template <class Arg, class... Args>
void ps(const Arg &first, const Args &...rest) {
  pr(first, " ");
  ps(rest...);
}
} // namespace __output
using namespace __output;

#define TRACE(x) x
#define __pn(x) pr(#x, " = ")
#define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush

namespace __algorithm {
template <typename T> void dedup(vector<T> &v) {
  sort(all(v));
  v.erase(unique(all(v)), v.end());
}
template <typename T>
typename vector<T>::const_iterator find(const vector<T> &v, const T &x) {
  auto it = lower_bound(all(v), x);
  return it != v.end() && *it == x ? it : v.end();
}
template <typename T> size_t index(const vector<T> &v, const T &x) {
  auto it = find(v, x);
  assert(it != v.end() && *it == x);
  return it - v.begin();
}

template <typename T1, typename T2>
typename vector<pair<T1, T2>>::iterator
lower_bound(const vector<pair<T1, T2>> &v, const T1 &x) {
  return lower_bound(all(v), x,
                     [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
}
template <typename T1, typename T2>
typename vector<pair<T1, T2>>::iterator
upper_bound(const vector<pair<T1, T2>> &v, const T1 &x) {
  return upper_bound(all(v), x,
                     [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
}
} // namespace __algorithm
using namespace __algorithm;

struct __monostate {
  friend istream &operator>>(istream &is,
                             const __attribute__((unused)) __monostate &ms) {
    return is;
  }
  friend ostream &operator<<(ostream &os,
                             const __attribute__((unused)) __monostate &ms) {
    return os;
  }
} ms;

namespace __io {
void setIn(string s) { freopen(s.c_str(), "r", stdin); }
void setOut(string s) { freopen(s.c_str(), "w", stdout); }
void setIO(string s = "") {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << setprecision(15);
  if (sz(s)) {
    setIn(s + ".in"), setOut(s + ".out");
  }
}
} // namespace __io
using namespace __io;
// }}}

// modnum {{{
using v_t = int;
using vv_t = ll;
template <v_t MOD> struct modnum {
  v_t v;
  modnum() : v(0) {}
  modnum(vv_t _v) : v(_v % MOD) {
    if (v < 0)
      v += MOD;
  }
  explicit operator v_t() const { return v; }
  friend istream &operator>>(istream &i, modnum &n) {
    vv_t w;
    i >> w;
    n = modnum(w);
    return i;
  }
  friend ostream &operator<<(ostream &o, const modnum &n) { return o << n.v; }

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

  static unsigned fast_mod(uint64_t x, unsigned m = MOD) {
#if !defined(_WIN32) || defined(_WIN64)
    return x % m;
#endif
    // x must be less than 2^32 * m so that x / m fits in a 32-bit integer.
    unsigned x_high = x >> 32, x_low = (unsigned)x, quot, rem;
    asm("divl %4\\n" : "=a"(quot), "=d"(rem) : "d"(x_high), "a"(x_low), "r"(m));
    return rem;
  }

  modnum &operator+=(const modnum &o) {
    v += o.v;
    if (v >= MOD)
      v -= MOD;
    return *this;
  }
  modnum &operator-=(const modnum &o) {
    v -= o.v;
    if (v < 0)
      v += MOD;
    return *this;
  }
  modnum &operator*=(const modnum &o) {
    v = fast_mod(vv_t(v) * o.v);
    return *this;
  }
  modnum operator-() {
    modnum res;
    if (v)
      res.v = MOD - v;
    return res;
  }
  friend modnum operator+(const modnum &a, const modnum &b) {
    return modnum(a) += b;
  }
  friend modnum operator-(const modnum &a, const modnum &b) {
    return modnum(a) -= b;
  }
  friend modnum operator*(const modnum &a, const modnum &b) {
    return modnum(a) *= b;
  }

  modnum pow(vv_t e) const {
    if (e < 0)
      return 1 / this->pow(-e);
    if (e == 0)
      return 1;
    if (e & 1)
      return *this * this->pow(e - 1);
    return (*this * *this).pow(e / 2);
  }

  modnum inv() const {
    v_t g = MOD, x = 0, y = 1;
    for (v_t r = v; r != 0;) {
      v_t q = g / r;
      g %= r;
      swap(g, r);
      x -= q * y;
      swap(x, y);
    }

    assert(g == 1);
    assert(y == MOD || y == -MOD);
    return x < 0 ? x + MOD : x;
  }
  modnum &operator/=(const modnum &o) { return (*this) *= o.inv(); }
  friend modnum operator/(const modnum &a, const modnum &b) {
    return modnum(a) /= modnum(b);
  }

  static constexpr v_t totient() {
    v_t tot = MOD, tmp = MOD;
    for (v_t p = 2; p * p <= tmp; p++)
      if (tmp % p == 0) {
        tot = tot / p * (p - 1);
        while (tmp % p == 0)
          tmp /= p;
      }
    if (tmp > 1)
      tot = tot / tmp * (tmp - 1);
    return tot;
  }

  static v_t primitive_root() {
    if (MOD == 1)
      return 0;
    if (MOD == 2)
      return 1;

    v_t tot = totient(), tmp = tot;
    vi tot_pr;
    for (v_t p = 2; p * p <= tmp; p++)
      if (tot % p == 0) {
        tot_pr.push_back(p);
        while (tmp % p == 0)
          tmp /= p;
      }
    if (tmp > 1)
      tot_pr.push_back(tmp);

    for (v_t r = 2; r < MOD; r++)
      if (__gcd(r, MOD) == 1) {
        bool root = true;
        for (v_t p : tot_pr)
          root &= modnum(r).pow(tot / p) != 1;
        if (root)
          return r;
      }
    assert(false);
  }

  static modnum generator() {
    static modnum g = primitive_root();
    return g;
  }
  static v_t discrete_log(modnum v) {
    static const v_t M = ceil(sqrt(MOD));
    static unordered_map<v_t, v_t> table;
    if (table.empty()) {
      modnum e = 1;
      for (v_t i = 0; i < M; i++) {
        table[e.v] = i;
        e *= generator();
      }
    }
    static modnum f = generator().pow(totient() - M);

    for (v_t i = 0; i < M; i++) {
      if (table.count(v.v))
        return table[v.v] + i * M;
      v *= f;
    }
    assert(false);
  }

  static modnum unity_root(int deg) {
    assert(totient() % deg == 0);
    return generator().pow(totient() / deg);
  }

  static modnum unity_root(int deg, int pow) {
    static vector<modnum> table{0, 1};
    while (sz(table) <= deg) {
      modnum w = unity_root(sz(table));
      for (int i = sz(table) / 2, s = sz(table); i < s; i++) {
        table.push_back(table[i]);
        table.push_back(table[i] * w);
      }
    }
    return table[deg + (pow < 0 ? deg + pow : pow)];
  }

  static modnum factorial(int n) {
    static vector<modnum> fact = {1};
    assert(n >= 0);
    if (sz(fact) <= n) {
      int had = sz(fact);
      fact.resize(n + 1);
      for (int i = had; i <= n; i++)
        fact[i] = fact[i - 1] * i;
    }
    return fact[n];
  }
  static modnum inverse_factorial(int n) {
    static vector<modnum> finv = {1};
    assert(n >= 0);
    if (sz(finv) <= n) {
      int had = sz(finv);
      finv.resz(n + 1), finv[n] = factorial(n).inv();
      for (int i = n - 1; i >= had; i--)
        finv[i] = finv[i + 1] * (i + 1);
    }
    return finv[n];
  }

  static modnum small_inv(int n) {
    assert(n > 0);
    return factorial(n - 1) * inverse_factorial(n);
  }

  static modnum ncr(int n, int r) {
    if (r < 0 || n < r)
      return 0;
    return factorial(n) * inverse_factorial(r) * inverse_factorial(n - r);
  }
};
// }}}
using mn = modnum<int(1e9 + 7)>;
using vmn = vector<mn>;
using vvmn = vector<vmn>;

int main() {
  setIO();

  int N, K;
  re(N, K);
  vi a(N);
  re(a);

  int neg = 0, zero = 0, pos = 0;
  trav(elt, a) {
    if (elt < 0)
      neg++;
    else if (elt == 0)
      zero++;
    else
      pos++;
  }

  if (K <= neg + pos) {
    sort(all(a));

    vi negs(a.begin(), a.begin() + neg);
    reverse(all(negs));

    vi poss(a.begin() + neg + zero, a.end());

    mn ans = 1;

    int n = 0, p = 0;
    F0R(i, K - (K & 1)) {
      int next_neg = n < neg ? negs[n] : 0;
      int next_pos = p < pos ? poss[p] : 0;
      if (abs(next_neg) > abs(next_pos)) {
        ans *= abs(next_neg);
        n++;
      } else {
        ans *= abs(next_pos);
        p++;
      }
    }

    if (K & 1) { // take one more positive or drop a pos and take two negs
      int opt1 = p < pos ? poss[p] : 0;

      if (p > 0 && n + 1 < N &&
          ll(opt1) * poss[p - 1] < ll(negs[n]) * negs[n + 1]) {
        ans = ans / poss[p - 1] * negs[n] * negs[n + 1];
      } else {
        ans *= opt1;
      }
    }

    if (ans.v != 0) {
      ps(ans);
      return 0;
    }
  }

  if (zero)
    ps(0);
  else {
    mn ans = 1;
    sort(all(a), [&](int x, int y) { return abs(x) < abs(y); });
    F0R(i, K) ans *= a[i];
    ps(ans);
  }

  return 0;
}