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

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

#define REP(i, n) for (int i = 0; i < n; i++)
#define REPR(i, n) for (int i = n; i >= 0; i--)
#define FOR(i, m, n) for (int i = m; i < n; i++)
#define ALL(obj) (obj).begin(), (obj).end()
#define INF 1e12
typedef long long ll;

//////////////////ここの値は必ず確認！！！！！////////////////////
//---------------------------------------------------------//
const int MOD = 1e9 + 7;
const int MAXR = 510000;
//---------------------------------------------------------//

template <ll mod> class modint {
public:
  ll val = 0;
  // コンストラクタ
  modint(ll x = 0) {
    while (x < 0)
      x += mod;
    val = x % mod;
  }
  // コピーコンストラクタ
  modint(const modint &r) { val = r.val; }
  // 算術演算子
  modint operator-() { return modint(-val); } // 単項
  modint operator+(const modint &r) { return modint(*this) += r; }
  modint operator-(const modint &r) { return modint(*this) -= r; }
  modint operator*(const modint &r) { return modint(*this) *= r; }
  modint operator/(const modint &r) { return modint(*this) /= r; }
  // 代入演算子
  modint &operator+=(const modint &r) {
    val += r.val;
    if (val >= mod)
      val -= mod;
    return *this;
  }
  modint &operator-=(const modint &r) {
    if (val < r.val)
      val += mod;
    val -= r.val;
    return *this;
  }
  modint &operator*=(const modint &r) {
    val = val * r.val % mod;
    return *this;
  }
  modint &operator/=(const modint &r) {
    ll a = r.val, b = mod, u = 1, v = 0;
    while (b) {
      ll t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    val = val * u % mod;
    if (val < 0)
      val += mod;
    return *this;
  }
  // 等価比較演算子
  bool operator==(const modint &r) { return this->val == r.val; }
  bool operator<(const modint &r) { return this->val < r.val; }
  bool operator!=(const modint &r) { return this->val != r.val; }
};

using mint = modint<MOD>;

// 入出力ストリーム
istream &operator>>(istream &is, mint &x) { // xにconst付けない
  ll t;
  is >> t;
  x = t;
  return (is);
}
ostream &operator<<(ostream &os, const mint &x) { return os << x.val; }

// 累乗
mint modpow(const mint &a, ll n) {
  if (n == 0)
    return 1;
  mint t = modpow(a, n / 2);
  t = t * t;
  if (n & 1)
    t = t * a;
  return t;
}

// 二項係数の計算
mint fac[MAXR + 1], finv[MAXR + 1], inv[MAXR + 1];
// テーブルの作成
void com_init() {
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  FOR(i, 2, MAXR) {
    fac[i] = fac[i - 1] * mint(i);
    inv[i] = -inv[MOD % i] * mint(MOD / i);
    finv[i] = finv[i - 1] * inv[i];
  }
}
// 演算部分
mint com(ll n, ll k) {
  if (n < k)
    return 0;
  if (n < 0)
    return 0;
  if (k == 0)
    return 1;
  return fac[n] * finv[k] * finv[n - k];
}

int main() {
  ll N, K;
  cin >> N >> K;

  vector<pair<ll, ll>> A;

  ll minus_count = 0;
  REP(i, N) {
    ll a;
    cin >> a;
    if (a > 0) {
      A.push_back({a, 1});
    } else if (a < 0) {
      A.push_back({-a, -1});
      minus_count++;
    } else if (a == 0) {
      A.push_back({0, 1});
    }
  }
  sort(ALL(A), greater<pair<ll, ll>>());

  ll ans = 1;

  if (K == N) { // K=Nの場合は全部かけるしかない
    REP(i, K) {
      ans *= A[i].first * A[i].second;
      ans %= MOD;
    }
    cout << (ans + MOD) % MOD << endl;
    return 0;
  }

  if (minus_count == N &&
      K % 2 == 1) { // 全部負で奇数個選ぶ場合は負になるしかない
    REP(i, K) {
      ans *= A[N - 1 - i].first * A[N - 1 - i].second;
      ans %= MOD;
    }
    cout << (ans + MOD) % MOD << endl;
    return 0;
  }

  REP(i, K) {
    ans *= A[i].first * A[i].second;
    ans %= MOD;
  }

  if (ans >= 0) {
    cout << ans << endl;
    return 0;
  } else if (ans < 0) {

    ll x1 = INF; // 負をぬく
    ll y1 = INF;

    ll x2 = INF; // 正をぬく
    ll y2 = INF;

    REP(i, K) {
      if (A[i].second == 1) {
        x2 = A[i].first * A[i].second;
      } else {
        x1 = A[i].first * A[i].second;
      }
    }
    for (int j = N - 1; j >= K; j--) {
      if (A[j].second == -1) {
        y2 = A[j].first * A[j].second;
      } else {
        y1 = A[j].first * A[j].second;
      }
    }

    mint a = ans;

    if (x1 == INF || y1 == INF) {
      a = a / mint(x2) * mint(y2);
    } else if (x2 == INF || y2 == INF) {
      a = a / mint(x1) * mint(y1);

    } else {
      if (x2 * y1 <= x1 * y2) {
        a = a / mint(x2) * mint(y2);
      } else {
        a = a / mint(x1) * mint(y1);
      }
    }

    cout << a << endl;
    return 0;
  }
}

Error: 0

Fixed submission:

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

#define REP(i, n) for (int i = 0; i < n; i++)
#define REPR(i, n) for (int i = n; i >= 0; i--)
#define FOR(i, m, n) for (int i = m; i < n; i++)
#define ALL(obj) (obj).begin(), (obj).end()
#define INF 1e9
typedef long long ll;

//---------------------------------------------------------//
const int MOD = 1e9 + 7;
const int MAXR = 510000;
//---------------------------------------------------------//

int main() {
  ll N, K;
  cin >> N >> K;

  deque<ll> A;
  vector<ll> AA;

  bool zeros = false;
  REP(i, N) {
    ll a;
    cin >> a;
    if (a != 0) {
      AA.push_back(a);
    } else {
      zeros = true;
    }
  }

  ll ans = 1;

  if (AA.size() < K) { // 0を含む必要があるなら
    cout << 0 << endl;
    return 0;
  }
  if (K == 1 && AA.size() == 1) {
    if (zeros) {
      ans = max(AA[0], ll(0));
    } else {
      ans = AA[0];
    }
    if (ans < 0) {
      ans += MOD;
    }
    ans %= MOD;
    cout << ans << endl;
    return 0;
  }

  if (K == 2 && AA.size() == 2) {
    if (zeros) {
      ans = max(AA[0] * AA[1], ll(0));
    } else {
      ans = AA[0] * AA[1];
    }
    ans %= MOD;
    if (ans < 0) {
      ans += MOD;
    }
    ans %= MOD;
    cout << ans << endl;
    return 0;
  }

  sort(ALL(AA), greater<ll>());
  REP(i, N) { A.push_back(AA[i]); }

  ll top = A.front();
  ll bottom = A.back();

  ll count = K;
  A.pop_front();
  A.pop_back();
  while (!A.empty()) {
    if (count == 1)
      break;
    if (abs(top) >= abs(bottom)) {
      ans *= top;
      ans %= MOD;
      top = A.front();
      A.pop_front();
      count--;
    } else if (abs(top) < abs(bottom)) {
      ans *= bottom;
      ans %= MOD;
      bottom = A.back();
      A.pop_back();
      count--;
    }
  }

  if (count == 2) { // A.size == K の場合
    if (zeros) {
      ans = max(ans * top * bottom, ll(0));
    } else {
      ans = ans * top * bottom;
    }
  } else { // count == 1
    if (zeros) {
      ans = max(ans * top, ll(0));
      ans = max(ans * bottom, ll(0));
    } else {
      ans = max(ans * top, ans * bottom);
    }
  }

  // 今度は最小をもとめる

  deque<ll> A_min;

  REP(i, N) { A_min.push_back(AA[i]); }

  top = A_min.front();
  bottom = A_min.back();

  ll ans_min = 1;
  count = K;
  A_min.pop_front();
  A_min.pop_back();
  while (!A_min.empty()) {
    // cout << ans_min << endl;
    if (count == 1)
      break;
    if (abs(top) < abs(bottom)) {
      ans_min *= top;
      ans_min %= MOD;
      top = A_min.front();
      A_min.pop_front();
      count--;
    } else if (abs(top) >= abs(bottom)) {
      ans_min *= bottom;
      ans_min %= MOD;
      bottom = A_min.back();
      A_min.pop_back();
      count--;
    }
  }

  if (count == 2) { // A.size == K の場合
    if (zeros) {
      ans_min = max((((ans_min * top) % MOD) * bottom) % MOD, ll(0));
    } else {
      ans_min = (((ans_min * top) % MOD) * bottom) % MOD;
    }
  } else { // count == 1
    if (zeros) {
      ans_min = max(ans_min * top % MOD, ll(0));
      ans_min = max(ans_min * bottom % MOD, ll(0));
    } else {
      ans_min = max(ans_min * top % MOD, ans_min * bottom % MOD);
    }
  }

  ans = max(ans, ans_min);
  if (ans < 0) {
    ans += MOD;
  }
  ans %= MOD;

  cout << ans << endl;

  return 0;
}