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

#ifndef __INTMOD_H__
#define __INTMOD_H__

/* updated: 2020-06-24 */

#include <cassert>
#include <cstdint>
#include <functional>
#include <iostream>
#include <unordered_map>
#include <vector>

template <uint32_t Mod> class IntMod {
  static_assert(Mod != 0, "Mod must not be 0");
  static_assert(Mod < 0x80000000, "Mod must be less than 0x80000000");

private:
  uint32_t value_m;

public:
  IntMod();
  IntMod(int32_t value);
  IntMod(uint32_t value);
  IntMod(int64_t value);
  IntMod(uint64_t value);

  const IntMod<Mod> &operator+() const;
  IntMod<Mod> operator-() const;
  IntMod<Mod> &operator++();
  IntMod<Mod> &operator--();
  IntMod<Mod> operator++(int dummy);
  IntMod<Mod> operator--(int dummy);
  IntMod<Mod> &operator+=(const IntMod<Mod> &right);
  IntMod<Mod> &operator-=(const IntMod<Mod> &right);
  IntMod<Mod> &operator*=(const IntMod<Mod> &right);
  IntMod<Mod> &operator/=(const IntMod<Mod> &right);
  IntMod<Mod> operator[](uint64_t exp) const;

  static IntMod<Mod> add(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> subtract(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> multiply(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> divide(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static int compare(const IntMod<Mod> &a, const IntMod<Mod> &b);

  IntMod<Mod> inverse() const;
  IntMod<Mod> power(uint64_t exp) const;
  uint32_t get() const;

  static IntMod<Mod> fact(uint32_t num);
  static IntMod<Mod> invFact(uint32_t num);
  static IntMod<Mod> combi(uint32_t n, uint32_t r);
  static IntMod<Mod> homcombi(uint32_t n, uint32_t r);
  static IntMod<Mod> perm(uint32_t n, uint32_t r);
  static std::vector<IntMod<Mod>> calcInverseList(int max);
};

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b);

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object);
template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object);

using MInt = IntMod<1000000007>;
using MF = IntMod<998244353>;

// for unordered_set/map
namespace std {
template <uint32_t Mod> struct hash<IntMod<Mod>> {
  size_t operator()(const IntMod<Mod> &object) const {
    return std::hash<uint32_t>()(object.get());
  }
};
} // namespace std

/*------------------------------------*/
/*-------   Implementations   --------*/
/*------------------------------------*/

template <uint32_t Mod> IntMod<Mod>::IntMod() : value_m(0) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int32_t value) {
  int32_t tmp = value % int32_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint32_t value) : value_m(value % Mod) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int64_t value) {
  int32_t tmp = value % int64_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint64_t value) : value_m(value % Mod) {}

template <uint32_t Mod> const IntMod<Mod> &IntMod<Mod>::operator+() const {
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator-() const {
  IntMod<Mod> ret;
  if (value_m == 0) {
    ret.value_m = 0;
  } else {
    ret.value_m = Mod - value_m;
  }
  return ret;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator++() {
  ++value_m;
  if (value_m == Mod) {
    value_m = 0;
  }
  return *this;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator--() {
  if (value_m == 0) {
    value_m = Mod;
  }
  --value_m;
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator++(int dummy) {
  IntMod ret(*this);
  ++*this;
  return ret;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator--(int dummy) {
  IntMod ret(*this);
  --*this;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator+=(const IntMod<Mod> &right) {
  value_m += right.value_m; // note: value_m < 0x80000000
  if (value_m >= Mod) {
    value_m -= Mod;
  }
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator-=(const IntMod<Mod> &right) {
  if (value_m < right.value_m) {
    value_m += Mod; // note: value_m < 0x80000000
  }
  value_m -= right.value_m;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator*=(const IntMod<Mod> &right) {
  value_m = (uint64_t(value_m) * right.value_m) % Mod;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator/=(const IntMod<Mod> &right) {
  *this *= right.inverse();
  return *this;
}

// for power
template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::operator[](uint64_t exp) const {
  return power(exp);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::add(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret += b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::subtract(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret -= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::multiply(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret *= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::divide(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret /= b;
  return ret;
}

template <uint32_t Mod>
int IntMod<Mod>::compare(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  if (a.value_m < b.value_m)
    return -1;
  if (a.value_m > b.value_m)
    return 1;
  return 0;
}

/* Mod must be a prime. */
template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::inverse() const {
  assert(value_m != 0);
  return power(Mod - 2);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::power(uint64_t exp) const {
  IntMod<Mod> product(1);
  IntMod<Mod> factor(*this);
  while (exp > 0) {
    if (exp & 1) {
      product *= factor;
    }
    factor *= factor;
    exp >>= 1;
  }
  return product;
}

template <uint32_t Mod> uint32_t IntMod<Mod>::get() const { return value_m; }

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::fact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  for (uint32_t i = old_size; i <= num; ++i) {
    table[i] = table[i - 1] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::invFact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  table[num] = fact(num).inverse();
  for (uint32_t i = num; i >= old_size; --i) {
    table[i - 1] = table[i] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::combi(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) * invFact(n - r) * invFact(r);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::homcombi(uint32_t n, uint32_t r) {
  assert(n != 0 || r == 0);

  if (n == 0 && r == 0)
    return IntMod<Mod>(1);
  return combi(n + r - 1, r);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::perm(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) * invFact(n - r);
}

template <uint32_t Mod>
std::vector<IntMod<Mod>> IntMod<Mod>::calcInverseList(int max) {
  assert(max < Mod);

  std::vector<IntMod<Mod>> table(max + 1);
  table[1] = 1;
  for (int i = 2; i <= max; ++i) {
    table[i] = (uint64_t(Mod - Mod / i) * table[Mod % i].get()) % Mod;
  }
  return table;
}

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::add(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::subtract(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::multiply(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::divide(a, b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b) {
  return a + IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b) {
  return a - IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b) {
  return a * IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b) {
  return a / IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) + b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) - b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) * b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) / b;
}

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) == 0;
}

template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) != 0;
}

template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) < 0;
}

template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) <= 0;
}

template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) > 0;
}

template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) >= 0;
}

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b) {
  return a == IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b) {
  return a != IntMod<Mod>(b);
}

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object) {
  uint64_t value;
  ist >> value;
  object = IntMod<Mod>(value);
  return ist;
}

template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object) {
  ost << object.get();
  return ost;
}

#endif

#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <vector>

using namespace std;
using uint = uint32_t;
using LL = int64_t;
using ULL = uint64_t;
using PP = pair<LL, LL>;
template <typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T>>;
#define REP(i, a, n) for (LL i = (a), i##_max_ = (n); i < i##_max_; ++i)
#define REM(i, a, n) for (LL i = (LL)(n)-1, i##_min_ = (a); i >= i##_min_; --i)
#define FLOAT fixed << setprecision(16)
#define SPEEDUP                                                                \\
  {                                                                            \\
    cin.tie(NULL);                                                             \\
    ios::sync_with_stdio(false);                                               \\
  }
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
template <class T, class U>
istream &operator>>(istream &ist, pair<T, U> &right) {
  return ist >> right.first >> right.second;
}
template <class T, class U>
ostream &operator<<(ostream &ost, const pair<T, U> &right) {
  return ost << right.first << ' ' << right.second;
}
template <class T, class TCompatible, size_t N>
void Fill(T (&dest)[N], const TCompatible &val) {
  fill(dest, dest + N, val);
}
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T (&dest)[M][N], const TCompatible &val) {
  for (int i = 0; i < M; ++i)
    Fill(dest[i], val);
}
template <class T> T Next() {
  T buf;
  cin >> buf;
  return buf;
}
istream &Ignore(istream &ist) {
  string s;
  ist >> s;
  return ist;
}
bool Inside(int i, int j, int h, int w) {
  return i >= 0 && i < h && j >= 0 && j < w;
}

#ifdef ONLY_MY_ENVIR
#include "Accumulator.h"
#include "Algebraic.h"
#include "BIT.h"
#include "BinaryMatrix.h"
#include "BinaryTree.h"
#include "Bipartite.h"
#include "Compressor.h"
#include "Decompositions.h"
#include "DiscreteLog.h"
#include "DynamicMod.h"
#include "Exponential.h"
#include "FFT.h"
#include "Factorization.h"
#include "FlowSolver.h"
#include "Graph.h"
#include "GraphUtil.h"
#include "IntMod.h"
#include "LIS.h"
#include "LazySegmentTree.h"
#include "Math.h"
#include "MathUtil.h"
#include "Matrix.h"
#include "MinCostFlowSolver.h"
#include "MinMax.h"
#include "Numbers.h"
#include "Optimize.h"
#include "Permutation.h"
#include "Polynomial.h"
#include "Position.h"
#include "Random.h"
#include "Range.h"
#include "Rational.h"
#include "RuntimeMod.h"
#include "SegmentTree.h"
#include "SegmentTree2D.h"
#include "Sets.h"
#include "Shortest.h"
#include "SlidingWindow.h"
#include "SpanningTree.h"
#include "StringSearching.h"
#include "SuffixArray.h"
#include "SwitchList.h"
#include "Timer.h"
#include "Tree.h"
#include "TreeUtil.h"
#include "UnionFind.h"
#include "Util.h"
#include "VectorUtil.h"
#endif

#ifdef __GNUC__
typedef __int128 LLL;
istream &operator>>(istream &ist, __int128 &val) {
  LL tmp;
  ist >> tmp;
  val = tmp;
  return ist;
}
ostream &operator<<(ostream &ost, __int128 val) {
  LL tmp = val;
  ost << tmp;
  return ost;
}
#endif

int N, K;
int A[200000];

MInt sub(int del, int add) {
  MInt ret = 1;
  REP(i, 0, K) {
    if (i == del)
      continue;
    ret *= A[i];
  }
  return ret * A[add];
}

int main() {
  cin >> N >> K;
  REP(i, 0, N) cin >> A[i];
  sort(A, A + N, [](int a, int b) { return abs(a) > abs(b); });

  if (K == N) {
    MInt ret = 1;
    REP(i, 0, N) { ret *= A[i]; }
    cout << ret << endl;
    return 0;
  }

  int mcnt = 0;
  REP(i, 0, N) mcnt += A[i] < 0;
  if (mcnt == N && K % 2 == 1) {
    MInt ret = 1;
    REP(i, 0, K) { ret *= A[N - 1 - i]; }
    cout << ret << endl;
    return 0;
  }

  MInt sum = 1;
  int cnt = 0;
  REP(i, 0, K) {
    if (A[i] < 0)
      ++cnt;
    sum *= abs(A[i]);
  }

  if (cnt % 2 == 0) {
    cout << sum << endl;
  } else {
    int lp = K - 1;
    int lm = K - 1;
    int rp = K;
    int rm = K;
    while (lp >= 0 && A[lp] < 0)
      --lp;
    while (lm >= 0 && A[lm] >= 0)
      --lm;
    while (rp < N && A[rp] < 0)
      ++rp;
    while (rm < N && A[rm] >= 0)
      ++rm;

    MInt ans;
    if (lp < 0 || rm >= N) {
      ans = sub(lm, rp);
    } else if (lm < 0 || rp >= N) {
      ans = sub(lp, rm);
    } else {
      if ((LL)A[rm] * A[lm] >= (LL)A[rp] * A[lp]) {
        ans = sub(lp, rm);
      } else {
        ans = sub(lm, rp);
      }
    }
    cout << ans << endl;
  }

  return 0;
}


Error: 0

Fixed submission:

#ifndef __INTMOD_H__
#define __INTMOD_H__

/* updated: 2020-06-24 */

#include <cassert>
#include <cstdint>
#include <functional>
#include <iostream>
#include <unordered_map>
#include <vector>

template <uint32_t Mod> class IntMod {
  static_assert(Mod != 0, "Mod must not be 0");
  static_assert(Mod < 0x80000000, "Mod must be less than 0x80000000");

private:
  uint32_t value_m;

public:
  IntMod();
  IntMod(int32_t value);
  IntMod(uint32_t value);
  IntMod(int64_t value);
  IntMod(uint64_t value);

  const IntMod<Mod> &operator+() const;
  IntMod<Mod> operator-() const;
  IntMod<Mod> &operator++();
  IntMod<Mod> &operator--();
  IntMod<Mod> operator++(int dummy);
  IntMod<Mod> operator--(int dummy);
  IntMod<Mod> &operator+=(const IntMod<Mod> &right);
  IntMod<Mod> &operator-=(const IntMod<Mod> &right);
  IntMod<Mod> &operator*=(const IntMod<Mod> &right);
  IntMod<Mod> &operator/=(const IntMod<Mod> &right);
  IntMod<Mod> operator[](uint64_t exp) const;

  static IntMod<Mod> add(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> subtract(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> multiply(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> divide(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static int compare(const IntMod<Mod> &a, const IntMod<Mod> &b);

  IntMod<Mod> inverse() const;
  IntMod<Mod> power(uint64_t exp) const;
  uint32_t get() const;

  static IntMod<Mod> fact(uint32_t num);
  static IntMod<Mod> invFact(uint32_t num);
  static IntMod<Mod> combi(uint32_t n, uint32_t r);
  static IntMod<Mod> homcombi(uint32_t n, uint32_t r);
  static IntMod<Mod> perm(uint32_t n, uint32_t r);
  static std::vector<IntMod<Mod>> calcInverseList(int max);
};

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b);

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object);
template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object);

using MInt = IntMod<1000000007>;
using MF = IntMod<998244353>;

// for unordered_set/map
namespace std {
template <uint32_t Mod> struct hash<IntMod<Mod>> {
  size_t operator()(const IntMod<Mod> &object) const {
    return std::hash<uint32_t>()(object.get());
  }
};
} // namespace std

/*------------------------------------*/
/*-------   Implementations   --------*/
/*------------------------------------*/

template <uint32_t Mod> IntMod<Mod>::IntMod() : value_m(0) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int32_t value) {
  int32_t tmp = value % int32_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint32_t value) : value_m(value % Mod) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int64_t value) {
  int32_t tmp = value % int64_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint64_t value) : value_m(value % Mod) {}

template <uint32_t Mod> const IntMod<Mod> &IntMod<Mod>::operator+() const {
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator-() const {
  IntMod<Mod> ret;
  if (value_m == 0) {
    ret.value_m = 0;
  } else {
    ret.value_m = Mod - value_m;
  }
  return ret;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator++() {
  ++value_m;
  if (value_m == Mod) {
    value_m = 0;
  }
  return *this;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator--() {
  if (value_m == 0) {
    value_m = Mod;
  }
  --value_m;
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator++(int dummy) {
  IntMod ret(*this);
  ++*this;
  return ret;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator--(int dummy) {
  IntMod ret(*this);
  --*this;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator+=(const IntMod<Mod> &right) {
  value_m += right.value_m; // note: value_m < 0x80000000
  if (value_m >= Mod) {
    value_m -= Mod;
  }
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator-=(const IntMod<Mod> &right) {
  if (value_m < right.value_m) {
    value_m += Mod; // note: value_m < 0x80000000
  }
  value_m -= right.value_m;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator*=(const IntMod<Mod> &right) {
  value_m = (uint64_t(value_m) * right.value_m) % Mod;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator/=(const IntMod<Mod> &right) {
  *this *= right.inverse();
  return *this;
}

// for power
template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::operator[](uint64_t exp) const {
  return power(exp);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::add(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret += b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::subtract(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret -= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::multiply(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret *= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::divide(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret /= b;
  return ret;
}

template <uint32_t Mod>
int IntMod<Mod>::compare(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  if (a.value_m < b.value_m)
    return -1;
  if (a.value_m > b.value_m)
    return 1;
  return 0;
}

/* Mod must be a prime. */
template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::inverse() const {
  assert(value_m != 0);
  return power(Mod - 2);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::power(uint64_t exp) const {
  IntMod<Mod> product(1);
  IntMod<Mod> factor(*this);
  while (exp > 0) {
    if (exp & 1) {
      product *= factor;
    }
    factor *= factor;
    exp >>= 1;
  }
  return product;
}

template <uint32_t Mod> uint32_t IntMod<Mod>::get() const { return value_m; }

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::fact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  for (uint32_t i = old_size; i <= num; ++i) {
    table[i] = table[i - 1] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::invFact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  table[num] = fact(num).inverse();
  for (uint32_t i = num; i >= old_size; --i) {
    table[i - 1] = table[i] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::combi(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) * invFact(n - r) * invFact(r);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::homcombi(uint32_t n, uint32_t r) {
  assert(n != 0 || r == 0);

  if (n == 0 && r == 0)
    return IntMod<Mod>(1);
  return combi(n + r - 1, r);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::perm(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) * invFact(n - r);
}

template <uint32_t Mod>
std::vector<IntMod<Mod>> IntMod<Mod>::calcInverseList(int max) {
  assert(max < Mod);

  std::vector<IntMod<Mod>> table(max + 1);
  table[1] = 1;
  for (int i = 2; i <= max; ++i) {
    table[i] = (uint64_t(Mod - Mod / i) * table[Mod % i].get()) % Mod;
  }
  return table;
}

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::add(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::subtract(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::multiply(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::divide(a, b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b) {
  return a + IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b) {
  return a - IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b) {
  return a * IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b) {
  return a / IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) + b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) - b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) * b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) / b;
}

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) == 0;
}

template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) != 0;
}

template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) < 0;
}

template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) <= 0;
}

template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) > 0;
}

template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) >= 0;
}

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b) {
  return a == IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b) {
  return a != IntMod<Mod>(b);
}

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object) {
  uint64_t value;
  ist >> value;
  object = IntMod<Mod>(value);
  return ist;
}

template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object) {
  ost << object.get();
  return ost;
}

#endif
#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <vector>

using namespace std;
using uint = uint32_t;
using LL = int64_t;
using ULL = uint64_t;
using PP = pair<LL, LL>;
template <typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T>>;
#define REP(i, a, n) for (LL i = (a), i##_max_ = (n); i < i##_max_; ++i)
#define REM(i, a, n) for (LL i = (LL)(n)-1, i##_min_ = (a); i >= i##_min_; --i)
#define FLOAT fixed << setprecision(16)
#define SPEEDUP                                                                \\
  {                                                                            \\
    cin.tie(NULL);                                                             \\
    ios::sync_with_stdio(false);                                               \\
  }
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
template <class T, class U>
istream &operator>>(istream &ist, pair<T, U> &right) {
  return ist >> right.first >> right.second;
}
template <class T, class U>
ostream &operator<<(ostream &ost, const pair<T, U> &right) {
  return ost << right.first << ' ' << right.second;
}
template <class T, class TCompatible, size_t N>
void Fill(T (&dest)[N], const TCompatible &val) {
  fill(dest, dest + N, val);
}
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T (&dest)[M][N], const TCompatible &val) {
  for (int i = 0; i < M; ++i)
    Fill(dest[i], val);
}
template <class T> T Next() {
  T buf;
  cin >> buf;
  return buf;
}
istream &Ignore(istream &ist) {
  string s;
  ist >> s;
  return ist;
}
bool Inside(int i, int j, int h, int w) {
  return i >= 0 && i < h && j >= 0 && j < w;
}

#ifdef ONLY_MY_ENVIR
#include "Accumulator.h"
#include "Algebraic.h"
#include "BIT.h"
#include "BinaryMatrix.h"
#include "BinaryTree.h"
#include "Bipartite.h"
#include "Compressor.h"
#include "Decompositions.h"
#include "DiscreteLog.h"
#include "DynamicMod.h"
#include "Exponential.h"
#include "FFT.h"
#include "Factorization.h"
#include "FlowSolver.h"
#include "Graph.h"
#include "GraphUtil.h"
#include "IntMod.h"
#include "LIS.h"
#include "LazySegmentTree.h"
#include "Math.h"
#include "MathUtil.h"
#include "Matrix.h"
#include "MinCostFlowSolver.h"
#include "MinMax.h"
#include "Numbers.h"
#include "Optimize.h"
#include "Permutation.h"
#include "Polynomial.h"
#include "Position.h"
#include "Random.h"
#include "Range.h"
#include "Rational.h"
#include "RuntimeMod.h"
#include "SegmentTree.h"
#include "SegmentTree2D.h"
#include "Sets.h"
#include "Shortest.h"
#include "SlidingWindow.h"
#include "SpanningTree.h"
#include "StringSearching.h"
#include "SuffixArray.h"
#include "SwitchList.h"
#include "Timer.h"
#include "Tree.h"
#include "TreeUtil.h"
#include "UnionFind.h"
#include "Util.h"
#include "VectorUtil.h"
#endif

#ifdef __GNUC__
typedef __int128 LLL;
istream &operator>>(istream &ist, __int128 &val) {
  LL tmp;
  ist >> tmp;
  val = tmp;
  return ist;
}
ostream &operator<<(ostream &ost, __int128 val) {
  LL tmp = val;
  ost << tmp;
  return ost;
}
#endif

int N, K;
int A[200000];

MInt sub(int del, int add) {
  MInt ret = 1;
  REP(i, 0, K) {
    if (i == del)
      continue;
    ret *= A[i];
  }
  return ret * A[add];
}

int main() {
  cin >> N >> K;
  REP(i, 0, N) cin >> A[i];
  sort(A, A + N, [](int a, int b) { return abs(a) > abs(b); });

  int mcnt = 0;
  REP(i, 0, N) mcnt += A[i] < 0;
  if (mcnt == N && K % 2 == 1) {
    MInt ret = 1;
    REP(i, 0, K) { ret *= A[N - 1 - i]; }
    cout << ret << endl;
    return 0;
  }

  MInt sum = 1;
  int cnt = 0;
  REP(i, 0, K) {
    if (A[i] < 0)
      ++cnt;
    sum *= abs(A[i]);
  }

  if (cnt % 2 == 0) {
    cout << sum << endl;
  } else {
    int lp = K - 1;
    int lm = K - 1;
    int rp = K;
    int rm = K;
    while (lp >= 0 && A[lp] < 0)
      --lp;
    while (lm >= 0 && A[lm] >= 0)
      --lm;
    while (rp < N && A[rp] < 0)
      ++rp;
    while (rm < N && A[rm] >= 0)
      ++rm;

    MInt ans;
    if (lp < 0 || rm >= N) {
      throw 1;
      ans = sub(lm, rp);
    } else if (lm < 0 || rp >= N) {
      throw 1;
      ans = sub(lp, rm);
    } else {
      if ((LL)A[rm] * A[lm] >= (LL)A[rp] * A[lp]) {
        ans = sub(lp, rm);
      } else {
        ans = sub(lm, rp);
      }
    }
    cout << ans << endl;
  }

  return 0;
}