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

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod = 1e9 + 7;
ll add(ll a, ll b) { return (a + b) % mod; }
ll mul(ll a, ll b) { return (a * b) % mod; }

ll mpow(ll a, ll b) {
  if (b == 0)
    return 1;
  ll res = mpow(mul(a, a), b / 2);
  if (b & 1)
    res = mul(res, a);
  return res;
}
ll divi(ll a, ll b) { return mul(a, mpow(b, mod - 2)); }

ll fact[3000005];
ll Fact[3000005];
typedef pair<ll, ll> P;

unordered_map<ll, ll> mem;

ll base = 10000000000LL;

ll nCr(ll n, ll r) {

  if (mem.count(n * base + r))
    return mem[n * base + r];

  return mem[n * base + r] = mul(fact[n], mul(Fact[r], Fact[n - r]));
}

ll nHr(ll n, ll r) {
  if (r == 0)
    return 1;
  return nCr(n + r - 1, r - 1);
}

ll nBr(ll n, ll r) {
  if (n < r)
    return 0;
  return nHr(n - r, r);
}

ll A, B, C, D, E;

int main() {
  fact[0] = 1;
  for (ll i = 1; i < 3000005; i++) {
    fact[i] = mul(fact[i - 1], i);
  }
  for (ll i = 0; i < 3000005; i++)
    Fact[i] = divi(1, fact[i]);

  while (1) {
    mem.clear();

    cin >> A >> B >> C >> D >> E;
    if (A == 0 && B == 0 && C == 0 && D == 0 && E == 0)
      break;

    ll ans = 0;
    for (ll i = 0; i <= 1000000; i++) {
      ll j = -(D - E - i);
      if (i < A)
        continue;
      if (A == 0 && i > 0)
        continue;
      if (i > D)
        continue;
      if (j < B)
        continue;
      if (B == 0 && j > 0)
        continue;
      if (j > E)
        continue;
      ll L = nBr(i, A);
      ll R = nBr(j, B);
      ll tmp = mul(L, R);
      tmp = mul(tmp, nCr(A + B, A));
      tmp = mul(tmp, nCr(A + B + C, C));
      assert(D - i == E - j);
      tmp = mul(tmp, nHr(D - i, A + B + C));
      ans = add(ans, tmp);
    }
    cout << ans << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod = 1e9 + 7;
ll add(ll a, ll b) { return (a + b) % mod; }
ll mul(ll a, ll b) { return (a * b) % mod; }

ll mpow(ll a, ll b) {
  if (b == 0)
    return 1;
  ll res = mpow(mul(a, a), b / 2);
  if (b & 1)
    res = mul(res, a);
  return res;
}
ll divi(ll a, ll b) { return mul(a, mpow(b, mod - 2)); }

ll fact[2000000];
ll Fact[2000000];
typedef pair<ll, ll> P;

unordered_map<ll, ll> mem;

ll base = 10000000000LL;

ll nCr(ll n, ll r) {

  if (mem.count(n * base + r))
    return mem[n * base + r];

  return mem[n * base + r] = mul(fact[n], mul(Fact[r], Fact[n - r]));
}

ll nHr(ll n, ll r) {
  if (r == 0)
    return 1;
  return nCr(n + r - 1, r - 1);
}

ll nBr(ll n, ll r) {
  if (n < r)
    return 0;
  return nHr(n - r, r);
}

ll A, B, C, D, E;

int main() {
  fact[0] = 1;
  for (ll i = 1; i < 2000000; i++) {
    fact[i] = mul(fact[i - 1], i);
  }
  for (ll i = 0; i < 2000000; i++)
    Fact[i] = divi(1, fact[i]);

  while (1) {
    mem.clear();

    cin >> A >> B >> C >> D >> E;
    if (A == 0 && B == 0 && C == 0 && D == 0 && E == 0)
      break;

    ll ans = 0;
    for (ll i = max(A, B + D - E); i <= D; i++) {
      ll j = -(D - E - i);
      //      if(i<A)continue;
      if (A == 0 && i > 0)
        continue;
      //      if(i>D)continue;
      //      if(j<B)continue;
      if (B == 0 && j > 0)
        break;
      if (j > E)
        break;
      ll L = nBr(i, A);
      ll R = nBr(j, B);
      ll tmp = mul(L, R);
      tmp = mul(tmp, nCr(A + B, A));
      tmp = mul(tmp, nCr(A + B + C, C));
      assert(D - i == E - j);
      tmp = mul(tmp, nHr(D - i, A + B + C));
      ans = add(ans, tmp);
    }
    cout << ans << endl;
  }
  return 0;
}