Problem p04004 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

int N, M, K, v[600009];
const int mod = 1e9 + 7;

int add(int x, int y) {
  int ans = x + y;
  if (ans >= mod)
    ans -= mod;
  return ans;
}
int subtract(int x, int y) {
  if (x >= y)
    return x - y;
  return x - y + mod;
}
int mul(int x, int y) { return 1LL * x * y % mod; }
void adto(int &x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
}

int power(int a, int b) {
  int p = 1;
  for (int i = 0; (1 << i) <= b; i++) {
    if (b & (1 << i))
      p = mul(p, a);
    a = mul(a, a);
  }
  return p;
}

int fac[1000009], inv[1000009], p3[1000009];
void Prec(int lim) {
  fac[0] = inv[0] = 1;
  for (int i = 1; i <= lim; i++)
    fac[i] = mul(fac[i - 1], i);
  inv[lim] = power(fac[lim], mod - 2);
  for (int i = lim - 1; i >= 1; i--)
    inv[i] = mul(inv[i + 1], i + 1);
}
int comb(int N, int K) {
  int ans = mul(fac[N], inv[N - K]);
  ans = mul(ans, inv[K]);
  return ans;
}

int main() {
  // freopen ("input", "r", stdin);
  // freopen ("output", "w", stdout);

  scanf("%d %d %d", &N, &M, &K), Prec(900003), p3[0] = 1;
  for (int i = 1; i <= 900000; i++)
    p3[i] = add(add(p3[i - 1], p3[i - 1]), p3[i - 1]);
  for (int i = 0; i <= M; i++)
    for (int j = 0; j <= K; j++)
      adto(v[i + j], comb(i + j, i));
  int ans = 0;
  for (int i = 0; i <= M + K; i++) {
    v[i] = mul(v[i], p3[M + K - i]);
    adto(ans, mul(v[i], comb(i + N - 1, N - 1)));
  }
  printf("%d\n", ans);
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;

int N, M, K, v[600009];
const int mod = 1e9 + 7;

int add(int x, int y) {
  int ans = x + y;
  if (ans >= mod)
    ans -= mod;
  return ans;
}
int subtract(int x, int y) {
  if (x >= y)
    return x - y;
  return x - y + mod;
}
int mul(int x, int y) { return 1LL * x * y % mod; }
void adto(int &x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
}

int power(int a, int b) {
  int p = 1;
  for (int i = 0; (1 << i) <= b; i++) {
    if (b & (1 << i))
      p = mul(p, a);
    a = mul(a, a);
  }
  return p;
}

int fac[1000009], inv[1000009], p3[1000009];
void Prec(int lim) {
  fac[0] = inv[0] = 1;
  for (int i = 1; i <= lim; i++)
    fac[i] = mul(fac[i - 1], i);
  inv[lim] = power(fac[lim], mod - 2);
  for (int i = lim - 1; i >= 1; i--)
    inv[i] = mul(inv[i + 1], i + 1);
}
int comb(int N, int K) {
  int ans = mul(fac[N], inv[N - K]);
  ans = mul(ans, inv[K]);
  return ans;
}

int main() {
  // freopen ("input", "r", stdin);
  // freopen ("output", "w", stdout);

  scanf("%d %d %d", &N, &M, &K), Prec(900003), p3[0] = 1;
  for (int i = 1; i <= 900000; i++)
    p3[i] = add(add(p3[i - 1], p3[i - 1]), p3[i - 1]);
  /*for (int i=0; i<=M; i++)
      for (int j=0; j<=K; j++)
          adto (v[i + j], comb (i + j, i));*/
  /*
  sa consideram un dreptunghi cu un colt in (0, 0) si unul in (M, K)
  pentru fiecare diagonala secundara, vrem sa stim numarul de drumuri
  care duc in diagonala aia
  */
  v[0] = 1;
  if (M > K)
    swap(M, K); /// M <= K
  for (int i = 1; i <= M + K; i++) {
    v[i] = add(v[i - 1], v[i - 1]);
    if (i > M)
      v[i] = subtract(v[i], comb(i - 1, M));
    if (i > K)
      v[i] = subtract(v[i], comb(i - 1, K));
  }
  int ans = 0;
  for (int i = 0; i <= M + K; i++) {
    v[i] = mul(v[i], p3[M + K - i]);
    adto(ans, mul(v[i], comb(i + N - 1, N - 1)));
  }
  printf("%d\n", ans);
  return 0;
}