Problem p04051 (C++)

Buggy submission (status: Runtime Error):
#include <iostream>
#include <utility>
#include <vector>

using namespace std;

long long pow_mod(long long b, long long p, long long mod = 1'000'000'007) {
  long long ret = 1;
  while (p) {
    if (p & 1)
      ret = (ret * b) % mod;
    b = (b * b) % mod;
    p >>= 1;
  }
  return ret;
}

long long inv_mod(long long n, long long mod = 1'000'000'007) {
  return pow_mod(n, mod - 2, mod);
}

class ModuloMath {
private:
  long long N;
  long long mod;
  vector<long long> fac;
  vector<long long> invfac;

public:
  ModuloMath(long long N, long long mod = 1'000'000'007) : N{N}, mod{mod} {
    fac.resize(N + 1, 1);
    invfac.resize(N + 1, 1);
    for (long long i = 1; i <= N; ++i)
      fac[i] = (fac[i - 1] * i) % mod;
    invfac[N] = pow_mod(fac[N], mod - 2, mod);
    for (long long i = N; i != 1; --i)
      invfac[i - 1] = (invfac[i] * i) % mod;
  }
  long long nCr(long long n, long long r) {
    return (r > n or r < 0) ? 0
                            : (fac[n] * invfac[n - r] % mod * invfac[r] % mod);
  }
  long long nPr(long long n, long long r) {
    return (r > n or r < 0) ? 0 : (fac[n] * invfac[n - r] % mod);
  }
  long long nHr(long long n, long long r) { return nCr(n + r - 1, r); }
};

constexpr long long mod = 1'000'000'007;
constexpr int offset = 10;

void print(const vector<vector<long long>> &mat) {
  for (auto &row : mat) {
    for (auto c : row)
      cout << c << ' ';
    cout << endl;
  }
  cout << endl;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  ModuloMath mm(offset * 4);
  int N;
  cin >> N;
  vector<pair<int, int>> AB(N);
  for (auto &p : AB)
    cin >> p.first >> p.second;
  vector<vector<long long>> dp(offset * 2, vector<long long>(offset * 2, 0LL));
  for (auto &p : AB)
    ++dp[offset - p.first][offset - p.second];
  for (int i = 1; i != offset * 2; ++i) {
    for (int j = 1; j != offset * 2; ++j) {
      dp[i][j] += (dp[i][j - 1] + dp[i - 1][j]) % mod;
    }
  }
  long long cum = 0LL;
  for (auto &p : AB) {
    cum = (cum + dp[offset + p.first][offset + p.second]) % mod;
    cum = (cum - mm.nCr((p.first + p.second) * 2, p.first * 2) + mod) % mod;
  }
  if (cum & 1)
    cum += mod;
  cout << (cum / 2) << endl;
  return 0;
}

Fixed submission:
#include <iostream>
#include <utility>
#include <vector>

using namespace std;

long long pow_mod(long long b, long long p, long long mod = 1'000'000'007) {
  long long ret = 1;
  while (p) {
    if (p & 1)
      ret = (ret * b) % mod;
    b = (b * b) % mod;
    p >>= 1;
  }
  return ret;
}

long long inv_mod(long long n, long long mod = 1'000'000'007) {
  return pow_mod(n, mod - 2, mod);
}

class ModuloMath {
private:
  long long N;
  long long mod;
  vector<long long> fac;
  vector<long long> invfac;

public:
  ModuloMath(long long N, long long mod = 1'000'000'007) : N{N}, mod{mod} {
    fac.resize(N + 1, 1);
    invfac.resize(N + 1, 1);
    for (long long i = 1; i <= N; ++i)
      fac[i] = (fac[i - 1] * i) % mod;
    invfac[N] = pow_mod(fac[N], mod - 2, mod);
    for (long long i = N; i != 1; --i)
      invfac[i - 1] = (invfac[i] * i) % mod;
  }
  long long nCr(long long n, long long r) {
    return (r > n or r < 0) ? 0
                            : (fac[n] * invfac[n - r] % mod * invfac[r] % mod);
  }
  long long nPr(long long n, long long r) {
    return (r > n or r < 0) ? 0 : (fac[n] * invfac[n - r] % mod);
  }
  long long nHr(long long n, long long r) { return nCr(n + r - 1, r); }
};

constexpr long long mod = 1'000'000'007;
constexpr int offset = 2002;

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  ModuloMath mm(offset * 4);
  int N;
  cin >> N;
  vector<pair<int, int>> AB(N);
  for (auto &p : AB)
    cin >> p.first >> p.second;
  vector<vector<long long>> dp(offset * 2, vector<long long>(offset * 2, 0LL));
  for (auto &p : AB)
    ++dp[offset - p.first][offset - p.second];
  for (int i = 1; i != offset * 2; ++i) {
    for (int j = 1; j != offset * 2; ++j) {
      dp[i][j] += (dp[i][j - 1] + dp[i - 1][j]) % mod;
    }
  }
  long long cum = 0LL;
  for (auto &p : AB) {
    cum = (cum + dp[offset + p.first][offset + p.second]) % mod;
    cum = (cum - mm.nCr((p.first + p.second) * 2, p.first * 2) + mod) % mod;
  }
  if (cum & 1)
    cum += mod;
  cout << (cum / 2) << endl;
  return 0;
}