Problem p03184 (C++)

Buggy submission (status: Runtime Error):
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <bits/stdc++.h>

using namespace std;

#define fo(i, a, b) for (int i = a; i <= b; i++)
#define _fo(i, a, b) for (int i = a; i >= b; i--)
#define foa(i, a) for (auto &i : a)
#define sz(a) ((int)a.size())
#define all(a) begin(a), end(a)
#define fi first
#define se second
#define pb(x) push_back(x)
#define mk(x, y) make_pair(x, y)

typedef int64_t ll;
typedef pair<ll, ll> pll;
typedef vector<ll> vl;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 2e3 + 5;
const int MAX = 2e5 + 5;
const int MOD = 1e9 + 7;
const ll INF = INT_MAX;
const ll _INF = INT_MIN;

pii bcell[N];
ll total[N];
ll fac[MAX], infac[MAX];

ll add(ll a, ll b) { return (a + b) % MOD; }
ll sub(ll a, ll b) { return (a - b + MOD) % MOD; }
ll mul(ll a, ll b) { return (a * b) % MOD; }

ll inv(ll val) {
  ll curr = 1, temp = MOD - 2;

  while (temp > 0) {
    if (temp & 1)
      curr = mul(curr, val);
    val = mul(val, val);
    temp >>= 1;
  }

  return curr;
}

void precompute(ll mx) {
  fac[0] = 1;
  fo(i, 1, mx) fac[i] = mul(i, fac[i - 1]);
  infac[mx] = inv(fac[mx]);
  _fo(i, mx - 1, 0) infac[i] = mul(i + 1, infac[i + 1]);
}

ll nCr(int a, int b) { return mul(mul(fac[a], infac[a - b]), infac[b]); }

ll solve(int n) {
  fo(i, 1, n) {
    ll curr = nCr(bcell[i].fi + bcell[i].se - 2, bcell[i].fi - 1), invalid = 0;
    _fo(j, i - 1, 1) {
      if (bcell[i].se >= bcell[j].se) {
        int dx = bcell[i].fi - bcell[j].fi, dy = bcell[i].se - bcell[j].se;
        invalid = add(invalid, mul(total[j], nCr(dx + dy, dx)));
      }
    }
    total[i] = sub(curr, invalid);
  }
  return total[n];
}

signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);

  int h, w, n;

  cin >> h >> w >> n;
  fo(i, 1, n) cin >> bcell[i].fi >> bcell[i].se;

  precompute(h + w);
  sort(bcell + 1, bcell + n + 1);
  bcell[++n] = {h, w};

  cout << solve(n);
}

Fixed submission:
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <bits/stdc++.h>

using namespace std;

#define fo(i, a, b) for (int i = a; i <= b; i++)
#define _fo(i, a, b) for (int i = a; i >= b; i--)
#define foa(i, a) for (auto &i : a)
#define sz(a) ((int)a.size())
#define all(a) begin(a), end(a)
#define fi first
#define se second
#define pb(x) push_back(x)
#define mk(x, y) make_pair(x, y)

typedef int64_t ll;
typedef pair<ll, ll> pll;
typedef vector<ll> vl;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 3e3 + 5;
const int MAX = 2e5 + 5;
const int MOD = 1e9 + 7;
const ll INF = INT_MAX;
const ll _INF = INT_MIN;

pii bcell[N];
ll total[N];
ll fac[MAX], infac[MAX];

ll add(ll a, ll b) { return (a + b) % MOD; }
ll sub(ll a, ll b) { return (a - b + MOD) % MOD; }
ll mul(ll a, ll b) { return (a * b) % MOD; }

ll inv(ll val) {
  ll curr = 1, temp = MOD - 2;

  while (temp > 0) {
    if (temp & 1)
      curr = mul(curr, val);
    val = mul(val, val);
    temp >>= 1;
  }

  return curr;
}

void precompute(ll mx) {
  fac[0] = 1;
  fo(i, 1, mx) fac[i] = mul(i, fac[i - 1]);
  infac[mx] = inv(fac[mx]);
  _fo(i, mx - 1, 0) infac[i] = mul(i + 1, infac[i + 1]);
}

ll nCr(int a, int b) { return mul(mul(fac[a], infac[a - b]), infac[b]); }

ll solve(int n) {
  fo(i, 1, n) {
    ll curr = nCr(bcell[i].fi + bcell[i].se - 2, bcell[i].fi - 1), invalid = 0;
    _fo(j, i - 1, 1) {
      if (bcell[i].se >= bcell[j].se) {
        int dx = bcell[i].fi - bcell[j].fi, dy = bcell[i].se - bcell[j].se;
        invalid = add(invalid, mul(total[j], nCr(dx + dy, dx)));
      }
    }
    total[i] = sub(curr, invalid);
  }
  return total[n];
}

signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);

  int h, w, n;

  cin >> h >> w >> n;
  fo(i, 1, n) cin >> bcell[i].fi >> bcell[i].se;

  precompute(h + w);
  sort(bcell + 1, bcell + n + 1);
  bcell[++n] = {h, w};

  cout << solve(n);
}