Problem p03152 (C++)

Buggy submission (status: Runtime Error):
#ifdef __LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;
template <typename T> bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
#define itn int
#define fi first
#define se second
#define intmax numeric_limits<int>::max()
#define llmax numeric_limits<ll>::max()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep1(i, n) for (int i = 1; i <= (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n)-1; i >= 0; i--)
#define rrep1(i, n) for (int i = (int)(n); i >= 1; i--)
#define all(vec) vec.begin(), vec.end()
#define sortt(vec) sort((vec).begin(), (vec).end())
#define rsort(vec) sort((vec).rbegin(), (vec).rend())
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef tuple<ll, ll, ll> tlll;
typedef tuple<int, int, int> tiii;
const ll mod = 1e9 + 7;
const int inf = 1 << 30;
const ll lnf = 1ll << 60;

struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream &operator>>(istream &is, mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }

mint cani[1010];
mint canj[1010];
mint scan[1000010];

int main() {
  itn n, m;
  cin >> n >> m;
  rep(i, n) {
    itn a;
    cin >> a;
    a--;
    cani[a] += 1;
    if (cani[a].x > 1) {
      cout << 0 << endl;
      return 0;
    }
  }
  rep(i, m) {
    itn b;
    cin >> b;
    b--;
    canj[b] += 1;
    if (canj[b].x > 1) {
      cout << 0 << endl;
      return 0;
    }
  }
  vector<mint> scani(n * m);
  scani[n * m - 1] = cani[n * m - 1];
  for (int i = n * m - 1; i > 0; i--)
    scani[i - 1] = scani[i] + cani[i - 1];
  vector<mint> scanj(n * m);
  scanj[n * m - 1] = canj[n * m - 1];
  for (int i = n * m - 1; i > 0; i--)
    scanj[i - 1] = scanj[i] + canj[i - 1];
  mint ans = 1;
  rrep(i, n * m) {
    if (cani[i].x > 0 && canj[i].x > 0)
      scan[i] = cani[i] * canj[i];
    else if (cani[i].x > 0)
      scan[i] = cani[i] * scanj[i];
    else if (canj[i].x > 0)
      scan[i] = scani[i] * canj[i];
    else
      scan[i] = scani[i] * scanj[i] - (n * m - 1 - i);
  }
  rrep(i, n * m) ans = ans * scan[i];
  cout << ans << endl;
}

Fixed submission:
#ifdef __LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;
template <typename T> bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
#define itn int
#define fi first
#define se second
#define intmax numeric_limits<int>::max()
#define llmax numeric_limits<ll>::max()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep1(i, n) for (int i = 1; i <= (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n)-1; i >= 0; i--)
#define rrep1(i, n) for (int i = (int)(n); i >= 1; i--)
#define all(vec) vec.begin(), vec.end()
#define sortt(vec) sort((vec).begin(), (vec).end())
#define rsort(vec) sort((vec).rbegin(), (vec).rend())
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef tuple<ll, ll, ll> tlll;
typedef tuple<int, int, int> tiii;
const ll mod = 1e9 + 7;
const int inf = 1 << 30;
const ll lnf = 1ll << 60;

struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream &operator>>(istream &is, mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }

mint cani[1000010];
mint canj[1000010];
mint scan[1000010];

int main() {
  itn n, m;
  cin >> n >> m;
  rep(i, n) {
    itn a;
    cin >> a;
    a--;
    cani[a] += 1;
    if (cani[a].x > 1) {
      cout << 0 << endl;
      return 0;
    }
  }
  rep(i, m) {
    itn b;
    cin >> b;
    b--;
    canj[b] += 1;
    if (canj[b].x > 1) {
      cout << 0 << endl;
      return 0;
    }
  }
  vector<mint> scani(n * m);
  scani[n * m - 1] = cani[n * m - 1];
  for (int i = n * m - 1; i > 0; i--)
    scani[i - 1] = scani[i] + cani[i - 1];
  vector<mint> scanj(n * m);
  scanj[n * m - 1] = canj[n * m - 1];
  for (int i = n * m - 1; i > 0; i--)
    scanj[i - 1] = scanj[i] + canj[i - 1];
  mint ans = 1;
  rrep(i, n * m) {
    if (cani[i].x > 0 && canj[i].x > 0)
      scan[i] = cani[i] * canj[i];
    else if (cani[i].x > 0)
      scan[i] = cani[i] * scanj[i];
    else if (canj[i].x > 0)
      scan[i] = scani[i] * canj[i];
    else
      scan[i] = scani[i] * scanj[i] - (n * m - 1 - i);
  }
  rrep(i, n * m) ans = ans * scan[i];
  cout << ans << endl;
}