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

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 200005;
vector<int> a;
bool cmp(const int &a, const int &b) { return abs(a) > abs(b); }
ll qpow(ll a, ll b) { // 快速幂
  ll res = 1;
  while (b) {
    if (b & 1)
      res = res * a % mod; // 可以换为快乘
    b >>= 1;
    a = a * a % mod;
  }
  return res;
}
ll exgcd(ll a, ll b, ll &x, ll &y) // 扩展欧几里得算法
{
  if (b == 0) {
    x = 1, y = 0;
    return a;
  }
  ll ret = exgcd(b, a % b, y, x);
  y -= a / b * x;
  return ret;
}
ll getInv(int a, int mod) // 求a在mod下的逆元，不存在逆元返回-1
{
  ll x, y;
  ll d = exgcd(a, mod, x, y);
  return d == 1 ? (x % mod + mod) % mod : -1;
}
int main() {
  // int test=100;
  // cout<<getInv(5, mod)<<endl;
  // test *= getInv(5, mod);
  // test %= mod;
  // cout<<(test%mod+mod)%mod<<endl;
  // test=100;
  // test *= qpow(5, mod - 2);
  // test %= mod;
  // test *= 4;
  // test %= mod;
  // cout<<(test%mod+mod)%mod<<endl;
  int n, k, z = 0;
  cin >> n >> k;
  for (int i = 0, b; i < n; i++) {
    cin >> b;
    if (b == 0)
      z++;
    else
      a.push_back(b);
  }
  if (k > (int)a.size()) {
    cout << 0 << endl;
    return 0;
  }
  sort(a.begin(), a.end(), cmp);
  ll ans = 1;
  int zheng = inf, fu = inf;    // 最后一个正数/负数
  for (int i = 0; i < k; i++) { // 前k个乘起来，存最后的正数和负数
    ans *= a[i];
    ans %= mod;
    if (a[i] > 0)
      zheng = a[i];
    else
      fu = a[i];
  }
  if (ans < 0) {
    int nzheng = inf, nfu = inf;            // 下一个正数和负数
    for (int i = k; i < (int)a.size(); i++) // k-后面里面找
      if (a[i] > 0 && nzheng == inf)
        nzheng = a[i]; // 只取最大的
      else if (a[i] < 0 && nfu == inf)
        nfu = a[i];
    if (nzheng == inf && nfu == inf) { // 没有别的数
      if (z > 0)                       // 出现0，答案变为0
        ans = 0;
    } else if (nzheng != inf && nfu == inf) { // 后面只有正
      ans *= qpow(fu, mod - 2); // 去掉最后一个最小的负数，乘上后面的正数
      ans %= mod;
      ans *= nzheng;
      ans %= mod;
    } else if (nzheng == inf && nfu != inf) { // 后面只有负数
      if (zheng != inf) {                     // 前面有正数
        ans *= qpow(zheng, mod - 2);          // 负数换正数
        ans %= mod;
        ans *= nfu;
        ans %= mod;
      } else { // 前面也没有正数，全是负数
        if (z > 0) {
          ans = 0;
        }
        // 全是负数，重新算答案
        else {
          ans = 1;
          for (int i = n - 1; i >= n - k; i--) { // 后k个数乘起来
            ans *= a[i];
            ans %= mod;
          }
        }
      }
    } else {              // 后面有正有负
      if (zheng == inf) { // 前面全是负数，正数换掉最小的负数
        ans *= qpow(fu, mod - 2);
        ans %= mod;
        ans *= nzheng;
        ans %= mod;
      } else if ((ll)zheng * nzheng < (ll)fu * nfu) {
        ans *= qpow(zheng, mod - 2);
        ans %= mod;
        ans *= nfu;
        ans %= mod;
      } else {
        ans *= qpow(fu, mod - 2);
        ans %= mod;
        ans *= nzheng;
        ans %= mod;
      }
    }
  }
  cout << (ans % mod + mod) % mod << endl;
  return 0;
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 200005;
vector<int> a;
bool cmp(const int &a, const int &b) { return abs(a) > abs(b); }
ll qpow(ll a, ll b) { // 快速幂
  ll res = 1;
  while (b) {
    if (b & 1)
      res = res * a % mod; // 可以换为快乘
    b >>= 1;
    a = a * a % mod;
  }
  return res;
}
int main() {
  int n, k, z = 0;
  cin >> n >> k;
  for (int i = 0, b; i < n; i++) {
    cin >> b;
    if (b == 0)
      z++;
    else
      a.push_back(b);
  }
  // if (k > (int)a.size()) {
  // 	cout << 0 << endl;
  // 	return 0;
  // }
  sort(a.begin(), a.end(), cmp);
  ll ans = 1;
  int zheng = 0, fu = 0;        // 最后一个正数/负数
  for (int i = 0; i < k; i++) { // 前k个乘起来，存最后的正数和负数
    ans *= a[i];
    ans %= mod;
    if (a[i] > 0)
      zheng = a[i];
    else
      fu = a[i];
  }
  if (ans < 0) {
    int nzheng = 0, nfu = 0;                // 下一个正数和负数
    for (int i = k; i < (int)a.size(); i++) // k-后面里面找
      if (a[i] > 0 && nzheng == 0)
        nzheng = a[i]; // 只取最大的
      else if (a[i] < 0 && nfu == 0)
        nfu = a[i];
    if (nzheng == 0 && nfu == 0) { // 没有别的数
      if (z > 0)                   // 出现0，答案变为0
        ans = 0;
    } else if (nzheng != 0 && nfu == 0) { // 后面只有正
      ans *= qpow(fu, mod - 2); // 去掉最后一个最小的负数，乘上后面的正数
      ans %= mod;
      ans *= nzheng;
      ans %= mod;
    } else if (nzheng == 0 && nfu != 0) { // 后面只有负数
      if (zheng != 0) {                   // 前面有正数
        ans *= qpow(zheng, mod - 2);      // 负数换正数
        ans %= mod;
        ans *= nfu;
        ans %= mod;
      } else { // 前面也没有正数，全是负数
        if (z > 0) {
          ans = 0;
        }
        // 全是负数，重新算答案
        else {
          ans = 1;
          for (int i = n - 1; i >= n - k; i--) { // 后k个数乘起来
            ans *= a[i];
            ans %= mod;
          }
        }
      }
    } else {            // 后面有正有负
      if (zheng == 0) { // 前面全是负数，正数换掉最小的负数
        ans *= qpow(fu, mod - 2);
        ans %= mod;
        ans *= nzheng;
        ans %= mod;
      } else if (zheng * nzheng <= fu * nfu) { // 后正数/前负数<后负数/前正数
        ans *= qpow(zheng, mod - 2);
        ans %= mod;
        ans *= nfu;
        ans %= mod;
      } else {
        ans *= qpow(fu, mod - 2);
        ans %= mod;
        ans *= nzheng;
        ans %= mod;
      }
    }
  }
  cout << (ans % mod + mod) % mod << endl;
  return 0;
}