Problem p03152 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <time.h>
#include <unordered_map>
#include <vector>
using namespace std;
using ll = long long;
using ld = long double;
using pint = pair<int, int>;
using pll = pair<ll, ll>;
#define MOD 1000000007LL
#define INF 1000000000LL
#define EPS 1e-10
#define FOR(i, n, m) for (ll i = n; i < (ll)m; i++)
#define REP(i, n) FOR(i, 0, n)
#define DUMP(a)                                                                \
  REP(d, a.size()) {                                                           \
    cout << a[d];                                                              \
    if (d != a.size() - 1)                                                     \
      cout << " ";                                                             \
    else                                                                       \
      cout << endl;                                                            \
  }
#define ALL(v) v.begin(), v.end()
#define UNIQUE(v)                                                              \
  sort(ALL(v));                                                                \
  v.erase(unique(ALL(v)), v.end());
#define pb push_back

#define MAX_N 2020
long long extgcd(long long a, long long b, long long &x, long long &y) {
  long long d = a;
  if (b != 0) {
    d = extgcd(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }
  return d;
}
long long mod_inverse(long long a, long long m) {
  long long x, y;
  if (extgcd(a, m, x, y) == 1)
    return (m + x % m) % m;
  else
    return -1;
}
vector<long long> fact(MAX_N + 1, INF);
long long mod_fact(long long n, long long &e) {
  if (fact[0] == INF) {
    fact[0] = 1;
    if (MAX_N != 0)
      fact[1] = 1;
    for (ll i = 2; i <= MAX_N; ++i) {
      fact[i] = (fact[i - 1] * i) % MOD;
    }
  }
  e = 0;
  if (n == 0)
    return 1;
  long long res = mod_fact(n / MOD, e);
  e += n / MOD;
  if ((n / MOD) % 2 != 0)
    return (res * (MOD - fact[n % MOD])) % MOD;
  return (res * fact[n % MOD]) % MOD;
}
// return nCk
long long mod_comb(long long n, long long k) {
  if (n < 0 || k < 0 || n < k)
    return 0;
  long long e1, e2, e3;
  long long a1 = mod_fact(n, e1), a2 = mod_fact(k, e2),
            a3 = mod_fact(n - k, e3);
  if (e1 > e2 + e3)
    return 0;
  return (a1 * mod_inverse((a2 * a3) % MOD, MOD)) % MOD;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll n, m;
  cin >> n >> m;
  vector<ll> modpow(2020, 0);
  modpow[0] = modpow[1] = 1;
  FOR(i, 2, 2020) {
    modpow[i] = i * modpow[i - 1];
    modpow[i] %= MOD;
  }
  vector<ll> a(n);
  vector<ll> b(m);
  REP(i, n) cin >> a[i];
  REP(i, m) cin >> b[i];
  REP(i, n) FOR(j, i + 1, n) {
    if (a[i] == a[j]) {
      cout << 0 << endl;
      return 0;
    }
  }
  REP(i, m) FOR(j, i + 1, m) {
    if (b[i] == b[j]) {
      cout << 0 << endl;
      return 0;
    }
  }
  vector<pll> v;
  REP(i, n) v.pb(pll(a[i], 0));
  REP(i, m) v.pb(pll(b[i], 1));
  sort(ALL(v));
  ll ans = 1;
  ll rem1 = n, rem2 = m;
  ll used = 0;
  REP(i, v.size()) {
    if (i < (ll)v.size() - 1 && v[i].first == v[i + 1].first) {
      if (v[i].first - used < rem1 + rem2 - 1) {
        cout << 0 << endl;
        return 0;
      }
      ans *= (modpow[rem1 + rem2 - 2] *
              mod_comb(v[i].first - used - 1, rem1 + rem2 - 2)) %
             MOD;
      ans %= MOD;
      used += rem1 + rem2 - 1;
      rem1--;
      rem2--;
      i++;
    } else {
      if (v[i].second == 0) {
        if (v[i].first - used < rem2) {
          cout << 0 << endl;
          return 0;
        }
        ans *= (modpow[rem2] * mod_comb(v[i].first - used - 1, rem2 - 1)) % MOD;
        ans %= MOD;
        used += rem2;
        rem1--;
      } else {
        if (v[i].first - used < rem1) {
          cout << 0 << endl;
          return 0;
        }
        ans *= (modpow[rem1] * mod_comb(v[i].first - used - 1, rem1 - 1)) % MOD;
        ans %= MOD;
        used += rem1;
        rem2--;
      }
    }
  }
  cout << ans << endl;
  return 0;
}

/* --------------------------------------- */


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <time.h>
#include <unordered_map>
#include <vector>
using namespace std;
using ll = long long;
using ld = long double;
using pint = pair<int, int>;
using pll = pair<ll, ll>;
#define MOD 1000000007LL
#define INF 1000000000LL
#define EPS 1e-10
#define FOR(i, n, m) for (ll i = n; i < (ll)m; i++)
#define REP(i, n) FOR(i, 0, n)
#define DUMP(a)                                                                \
  REP(d, a.size()) {                                                           \
    cout << a[d];                                                              \
    if (d != a.size() - 1)                                                     \
      cout << " ";                                                             \
    else                                                                       \
      cout << endl;                                                            \
  }
#define ALL(v) v.begin(), v.end()
#define UNIQUE(v)                                                              \
  sort(ALL(v));                                                                \
  v.erase(unique(ALL(v)), v.end());
#define pb push_back

#define MAX_N 1000100
long long extgcd(long long a, long long b, long long &x, long long &y) {
  long long d = a;
  if (b != 0) {
    d = extgcd(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }
  return d;
}
long long mod_inverse(long long a, long long m) {
  long long x, y;
  if (extgcd(a, m, x, y) == 1)
    return (m + x % m) % m;
  else
    return -1;
}
vector<long long> fact(MAX_N + 1, INF);
long long mod_fact(long long n, long long &e) {
  if (fact[0] == INF) {
    fact[0] = 1;
    if (MAX_N != 0)
      fact[1] = 1;
    for (ll i = 2; i <= MAX_N; ++i) {
      fact[i] = (fact[i - 1] * i) % MOD;
    }
  }
  e = 0;
  if (n == 0)
    return 1;
  long long res = mod_fact(n / MOD, e);
  e += n / MOD;
  if ((n / MOD) % 2 != 0)
    return (res * (MOD - fact[n % MOD])) % MOD;
  return (res * fact[n % MOD]) % MOD;
}
// return nCk
long long mod_comb(long long n, long long k) {
  if (n < 0 || k < 0 || n < k)
    return 0;
  long long e1, e2, e3;
  long long a1 = mod_fact(n, e1), a2 = mod_fact(k, e2),
            a3 = mod_fact(n - k, e3);
  if (e1 > e2 + e3)
    return 0;
  return (a1 * mod_inverse((a2 * a3) % MOD, MOD)) % MOD;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll n, m;
  cin >> n >> m;
  vector<ll> modpow(2020, 0);
  modpow[0] = modpow[1] = 1;
  FOR(i, 2, 2020) {
    modpow[i] = i * modpow[i - 1];
    modpow[i] %= MOD;
  }
  vector<ll> a(n);
  vector<ll> b(m);
  REP(i, n) cin >> a[i];
  REP(i, m) cin >> b[i];
  REP(i, n) FOR(j, i + 1, n) {
    if (a[i] == a[j]) {
      cout << 0 << endl;
      return 0;
    }
  }
  REP(i, m) FOR(j, i + 1, m) {
    if (b[i] == b[j]) {
      cout << 0 << endl;
      return 0;
    }
  }
  vector<pll> v;
  REP(i, n) v.pb(pll(a[i], 0));
  REP(i, m) v.pb(pll(b[i], 1));
  sort(ALL(v));
  ll ans = 1;
  ll rem1 = n, rem2 = m;
  ll used = 0;
  REP(i, v.size()) {
    if (i < (ll)v.size() - 1 && v[i].first == v[i + 1].first) {
      if (v[i].first - used < rem1 + rem2 - 1) {
        cout << 0 << endl;
        return 0;
      }
      ans *= (modpow[rem1 + rem2 - 2] *
              mod_comb(v[i].first - used - 1, rem1 + rem2 - 2)) %
             MOD;
      ans %= MOD;
      used += rem1 + rem2 - 1;
      rem1--;
      rem2--;
      i++;
    } else {
      if (v[i].second == 0) {
        if (v[i].first - used < rem2) {
          cout << 0 << endl;
          return 0;
        }
        ans *= (modpow[rem2] * mod_comb(v[i].first - used - 1, rem2 - 1)) % MOD;
        ans %= MOD;
        used += rem2;
        rem1--;
      } else {
        if (v[i].first - used < rem1) {
          cout << 0 << endl;
          return 0;
        }
        ans *= (modpow[rem1] * mod_comb(v[i].first - used - 1, rem1 - 1)) % MOD;
        ans %= MOD;
        used += rem1;
        rem2--;
      }
    }
  }
  cout << ans << endl;
  return 0;
}

/* --------------------------------------- */