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

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

typedef long int ll;
typedef vector<ll> vint;
typedef vector<vector<ll>> vvint;

#define rep(i, n) for (ll i = 0; i < n; i++)
#define repf(i, f, n) for (ll i = f; i < n; i++)
#define repr(i, n) for (ll i = n - 1; i >= 0; i--)
#define mp make_pair
#define mt make_tuple
#define ALL(obj) (obj).begin(), (obj).end()
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

int dy[] = {0, 0, 1, -1, 1, -1, -1, 1};
int dx[] = {1, -1, 0, 0, 1, 1, -1, -1};

template <int mod> struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while (n > 0) {
      if (n & 1)
        ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt<(int)(1e9 + 7)>;

template <typename T> struct Combination {
  vector<T> _fact, _rfact, _inv;

  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for (int i = 1; i <= sz; i++)
      _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for (int i = sz - 1; i >= 0; i--)
      _rfact[i] = _rfact[i + 1] * (i + 1);
    for (int i = 1; i <= sz; i++)
      _inv[i] = _rfact[i] * _fact[i - 1];
  }

  inline T fact(int k) const { return _fact[k]; }

  inline T rfact(int k) const { return _rfact[k]; }

  inline T inv(int k) const { return _inv[k]; }

  T P(int n, int r) const {
    if (r < 0 || n < r)
      return 0;
    return fact(n) * rfact(n - r);
  }

  T C(int p, int q) const {
    if (q < 0 || p < q)
      return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }

  T H(int n, int r) const {
    if (n < 0 || r < 0)
      return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};

template <class Int> struct Fraction { //{{{
  Int num, den;

private:
  static Int gcd(Int a, Int b) {
    while (b)
      swap(a %= b, b);
    return a;
  }
  void normalize() {
    Int g = gcd(num, den);
    num /= g;
    den /= g;
    if (den < 0) {
      num = -num;
      den = -den;
    }
  }

public:
  Fraction(Int num) : num(num), den(1) {}
  Fraction(Int num, Int den, bool need_normalize = true) : num(num), den(den) {
    if (need_normalize)
      normalize();
  }

  Fraction operator-() const { return Fraction(-num, den, false); }
}; //}}}

using Z = int64_t;
using Q = Fraction<Z>;

// int sgn(const Z a){
//     return (a > 0) - (a < 0);
// }
int sgn(const Z a, const Z b) {
  return (a > b) - (a < b); // sgn(a-b) にするとオーバーフローしやすい.
}
// int sgn(const Q &a){
//     return sgn(a.num);
// }
// int sgn(const Q &a, const Q &b){
//     return sgn(a.num * b.den, b.num * a.den); // オーバーフローしやすい.
// }

int sgn(Q a, Q b) {
  if (a.num <= 0 or b.num <= 0) {
    if (a.num == 0 or b.num == 0)
      return sgn(a.num, b.num);
    if ((a.num < 0) xor (b.num < 0))
      return sgn(a.num, b.num);
    return sgn(-b, -a);
  }
  int flip = 1;
  while (a.den != 0 and b.den != 0) {
    if (int s = sgn(a.num / a.den, b.num / b.den))
      return s * flip;
    swap(a.num %= a.den, a.den);
    swap(b.num %= b.den, b.den);
    flip = -flip;
  }
  return flip * sgn(a.num * b.den, a.den * b.num);
}

int main() {
  cout << fixed << setprecision(10);

  // auto a = Fraction<ll>(4, 5);
  // auto b = Fraction<ll>(5,6);

  // cout<<sgn(a,b)<<endl; //
  // cout<<sgn(b,a)<<endl;

  ll n, k;
  cin >> n >> k;
  vint a(n);
  rep(i, n) cin >> a[i];

  using P = pair<ll, ll>;
  vector<P> vp;
  for (auto e : a) {
    if (e < 0) {
      vp.emplace_back(-e, 1);
    } else {
      vp.emplace_back(e, 0);
    }
  }
  sort(ALL(vp), greater<P>());

  ll posi, negi;
  posi = -1;
  negi = -1;
  ll negcnt = 0;
  rep(i, k) {
    ll e, t;
    tie(e, t) = vp[i];
    if (t == 1) {
      negcnt++;
      negi = i;
    } else {
      posi = i;
    }
  }

  if (vp[k - 1].first == 0) {
    cout << 0 << endl;
    return 0;
  }
  if (k == n) {
    modint ans = 1;
    rep(i, k) ans *= a[i];
    cout << ans << endl;
    return 0;
  }

  if (negcnt % 2 == 0) {
    modint ans = 1;
    rep(i, k) ans *= vp[i].first;
    cout << ans << endl;
    return 0;

  } else {
    if (posi == -1) {
      ll num = -1;
      repf(i, k, n) {
        ll e, t;
        tie(e, t) = vp[i];
        if (t == 1)
          continue;
        num = 1;
        swap(vp[negi], vp[i]);
        break;
      }
      if (num == -1) {
        // 負の数だけで
        modint ans = 1;
        rep(i, k) { ans *= vp[n - 1 - i].first; }
        ans *= -1;
        cout << ans << endl;
        return 0;

      } else {
        //    auto x = Fraction<ll>(num, vp[negi].first);
        modint ans = 1;
        rep(i, k) ans *= vp[i].first;
        cout << ans << endl;
        return 0;
      }
    } else {
      // auto x = Fraction<ll>(1);
      // auto y = Fraction<ll>(1);
      using D = long double;
      D x, y;
      x = y = 0;

      bool nf, pf;
      nf = false;
      pf = false;
      ll nposi, nnegi;
      nposi = nnegi = -1;
      repf(i, k, n) {
        ll e, t;
        tie(e, t) = vp[i];
        if (t == 1) {
          if (nf == false) {
            // x = Fraction<ll>(e, vp[posi].first);
            x = D(e) / vp[posi].first;
            nnegi = i;
            nf = true;
          }
        } else {
          if (pf == false) {
            // y = Fraction<ll>(e, vp[negi].first);
            y = D(e) / vp[negi].first;
            nposi = i;
            pf = true;
          }
        }
        if (nf and pf)
          break;
      }

      modint ans = 1;

      // if(sgn(x,y) < 0){
      if (x < y) {
        // yがおおきい
        swap(vp[negi], vp[nposi]);
        rep(i, k) { ans *= vp[i].first; }
      } else {
        // xがおおきい
        swap(vp[posi], vp[nnegi]);
        rep(i, k) { ans *= vp[i].first; }
      }
      cout << ans << endl;
    }
  }

  return 0;
}

Error: 0

Fixed submission:

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

typedef long int ll;
typedef vector<ll> vint;
typedef vector<vector<ll>> vvint;

#define rep(i, n) for (ll i = 0; i < n; i++)
#define repf(i, f, n) for (ll i = f; i < n; i++)
#define repr(i, n) for (ll i = n - 1; i >= 0; i--)
#define mp make_pair
#define mt make_tuple
#define ALL(obj) (obj).begin(), (obj).end()
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

int dy[] = {0, 0, 1, -1, 1, -1, -1, 1};
int dx[] = {1, -1, 0, 0, 1, 1, -1, -1};

template <int mod> struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while (n > 0) {
      if (n & 1)
        ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt<(int)(1e9 + 7)>;

template <typename T> struct Combination {
  vector<T> _fact, _rfact, _inv;

  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for (int i = 1; i <= sz; i++)
      _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for (int i = sz - 1; i >= 0; i--)
      _rfact[i] = _rfact[i + 1] * (i + 1);
    for (int i = 1; i <= sz; i++)
      _inv[i] = _rfact[i] * _fact[i - 1];
  }

  inline T fact(int k) const { return _fact[k]; }

  inline T rfact(int k) const { return _rfact[k]; }

  inline T inv(int k) const { return _inv[k]; }

  T P(int n, int r) const {
    if (r < 0 || n < r)
      return 0;
    return fact(n) * rfact(n - r);
  }

  T C(int p, int q) const {
    if (q < 0 || p < q)
      return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }

  T H(int n, int r) const {
    if (n < 0 || r < 0)
      return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};

template <class Int> struct Fraction { //{{{
  Int num, den;

private:
  static Int gcd(Int a, Int b) {
    while (b)
      swap(a %= b, b);
    return a;
  }
  void normalize() {
    Int g = gcd(num, den);
    num /= g;
    den /= g;
    if (den < 0) {
      num = -num;
      den = -den;
    }
  }

public:
  Fraction(Int num) : num(num), den(1) {}
  Fraction(Int num, Int den, bool need_normalize = true) : num(num), den(den) {
    if (need_normalize)
      normalize();
  }

  Fraction operator-() const { return Fraction(-num, den, false); }
}; //}}}

using Z = int64_t;
using Q = Fraction<Z>;

// int sgn(const Z a){
//     return (a > 0) - (a < 0);
// }
int sgn(const Z a, const Z b) {
  return (a > b) - (a < b); // sgn(a-b) にするとオーバーフローしやすい.
}
// int sgn(const Q &a){
//     return sgn(a.num);
// }
// int sgn(const Q &a, const Q &b){
//     return sgn(a.num * b.den, b.num * a.den); // オーバーフローしやすい.
// }

int sgn(Q a, Q b) {
  if (a.num <= 0 or b.num <= 0) {
    if (a.num == 0 or b.num == 0)
      return sgn(a.num, b.num);
    if ((a.num < 0) xor (b.num < 0))
      return sgn(a.num, b.num);
    return sgn(-b, -a);
  }
  int flip = 1;
  while (a.den != 0 and b.den != 0) {
    if (int s = sgn(a.num / a.den, b.num / b.den))
      return s * flip;
    swap(a.num %= a.den, a.den);
    swap(b.num %= b.den, b.den);
    flip = -flip;
  }
  return flip * sgn(a.num * b.den, a.den * b.num);
}

int main() {
  cout << fixed << setprecision(10);

  // auto a = Fraction<ll>(4, 5);
  // auto b = Fraction<ll>(5,6);

  // cout<<sgn(a,b)<<endl; //
  // cout<<sgn(b,a)<<endl;

  ll n, k;
  cin >> n >> k;
  vint a(n);
  rep(i, n) cin >> a[i];

  using P = pair<ll, ll>;
  vector<P> vp;
  for (auto e : a) {
    if (e < 0) {
      vp.emplace_back(-e, 1);
    } else {
      vp.emplace_back(e, 0);
    }
  }
  sort(ALL(vp), greater<P>());

  ll posi, negi;
  posi = -1;
  negi = -1;
  ll negcnt = 0;
  rep(i, k) {
    ll e, t;
    tie(e, t) = vp[i];
    if (t == 1) {
      negcnt++;
      negi = i;
    } else {
      posi = i;
    }
  }

  if (vp[k - 1].first == 0) {
    cout << 0 << endl;
    return 0;
  }
  if (k == n) {
    modint ans = 1;
    rep(i, k) ans *= a[i];
    cout << ans << endl;
  }

  if (negcnt % 2 == 0) {
    modint ans = 1;
    rep(i, k) ans *= vp[i].first;
    cout << ans << endl;
    return 0;

  } else {
    if (posi == -1) {
      ll num = -1;
      repf(i, k, n) {
        ll e, t;
        tie(e, t) = vp[i];
        if (t == 1)
          continue;
        num = 1;
        swap(vp[negi], vp[i]);
        break;
      }
      if (num == -1) {
        // 負の数だけで
        modint ans = 1;
        rep(i, k) { ans *= vp[n - 1 - i].first; }
        ans *= -1;
        cout << ans << endl;
        return 0;

      } else {
        //    auto x = Fraction<ll>(num, vp[negi].first);
        modint ans = 1;
        rep(i, k) ans *= vp[i].first;
        cout << ans << endl;
        return 0;
      }
    } else {
      // auto x = Fraction<ll>(1);
      // auto y = Fraction<ll>(1);
      using D = long double;
      D x, y;
      x = y = 0;

      bool nf, pf;
      nf = false;
      pf = false;
      ll nposi, nnegi;
      nposi = nnegi = -1;
      repf(i, k, n) {
        ll e, t;
        tie(e, t) = vp[i];
        if (t == 1) {
          if (nf == false) {
            // x = Fraction<ll>(e, vp[posi].first);
            x = D(e) / vp[posi].first;
            nnegi = i;
            nf = true;
          }
        } else {
          if (pf == false) {
            // y = Fraction<ll>(e, vp[negi].first);
            y = D(e) / vp[negi].first;
            nposi = i;
            pf = true;
          }
        }
        if (nf and pf)
          break;
      }

      modint ans = 1;

      // if(sgn(x,y) < 0){
      if (x < y) {
        // yがおおきい
        swap(vp[negi], vp[nposi]);
        rep(i, k) { ans *= vp[i].first; }
      } else {
        // xがおおきい
        swap(vp[posi], vp[nnegi]);
        rep(i, k) { ans *= vp[i].first; }
      }
      cout << ans << endl;
    }
  }

  return 0;
}