Problem p03622 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

typedef long long i64;
const int MOD = 998244353, MAX_N = 1000005;

i64 fac[MAX_N], ifac[MAX_N], inv[MAX_N];
int N, M;

i64 binom(int n, int m) {
  if (n < m)
    return 0;
  return fac[n] * ifac[m] % MOD * ifac[n - m] % MOD;
}

i64 res[MAX_N], temp[MAX_N];

int main() {
  scanf("%d%d", &N, &M);

  if (N > M)
    swap(N, M);

  fac[0] = ifac[0] = inv[1] = 1;
  for (int i = 1; i <= N + M; ++i)
    fac[i] = fac[i - 1] * i % MOD;
  for (int i = 2; i <= N + M; ++i)
    inv[i] = (-(MOD / i) * inv[MOD % i] % MOD + MOD) % MOD;
  for (int i = 1; i <= N + M; ++i)
    ifac[i] = ifac[i - 1] * inv[i] % MOD;

  for (int i = 0; i <= N; ++i)
    for (int j = 0; j <= M; ++j)
      temp[i + j] = (temp[i + j] + max(i, j) * binom(i + j, j) % MOD *
                                       binom(N - i + M - j, N - i) % MOD) %
                    MOD;

  i64 horizon = binom(N + M - 1, N), vertical = binom(N + M - 1, N - 1);

  for (int i = 1; i <= N + M; ++i) {
    res[i] = (res[i - 1] + horizon + vertical) % MOD;

    if (i <= N * 2) {
      if (!(i & 1)) {
        horizon = (horizon + binom(N + M - 1 - i, M - i / 2 - 1) *
                                 binom(i - 1, i / 2) % MOD) %
                  MOD;
        vertical = (vertical +
                    binom(N + M - 1 - i, N - i / 2 - 1) * binom(i - 1, i / 2)) %
                   MOD;
      } else {
        horizon = (horizon - binom(N + M - 1 - i, M - i / 2 - 1) *
                                 binom(i - 1, i / 2) % MOD) %
                  MOD;
        vertical = (vertical - binom(N + M - 1 - i, N - i / 2 - 1) *
                                   binom(i - 1, i / 2) % MOD) %
                   MOD;
      }
    }
    if (i >= N * 2)
      vertical = 0;
    // if (i >= M && M > 1) horizon = (horizon - binom((i - M) + M - 1, M - 1))
    // % MOD; if (i >= N && i < N * 2 && N > 1) vertical = (vertical - binom((i
    // - N) + N - 1, N - 1)) % MOD;
  }

  i64 result = 0;
  for (int i = 1; i <= N + M; ++i)
    result = (result + res[i] * inv[i] % MOD) % MOD;
  result = result * fac[N] % MOD * fac[M] % MOD * ifac[N + M] % MOD;
  printf("%lld\n", (result + MOD) % MOD);
  return 0;
}


Fixed submission:
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

typedef long long i64;
const int MOD = 998244353, MAX_N = 1000005;

i64 fac[MAX_N], ifac[MAX_N], inv[MAX_N];
int N, M;

i64 binom(int n, int m) {
  if (n < m)
    return 0;
  return fac[n] * ifac[m] % MOD * ifac[n - m] % MOD;
}

i64 res[MAX_N], temp[MAX_N];

int main() {
  scanf("%d%d", &N, &M);

  if (N > M)
    swap(N, M);

  fac[0] = ifac[0] = inv[1] = 1;
  for (int i = 1; i <= N + M; ++i)
    fac[i] = fac[i - 1] * i % MOD;
  for (int i = 2; i <= N + M; ++i)
    inv[i] = (-(MOD / i) * inv[MOD % i] % MOD + MOD) % MOD;
  for (int i = 1; i <= N + M; ++i)
    ifac[i] = ifac[i - 1] * inv[i] % MOD;

  i64 horizon = binom(N + M - 1, N), vertical = binom(N + M - 1, N - 1);

  for (int i = 1; i <= N + M; ++i) {
    res[i] = (res[i - 1] + horizon + vertical) % MOD;

    if (i <= N * 2) {
      if (!(i & 1)) {
        horizon = (horizon + binom(N + M - 1 - i, M - i / 2 - 1) *
                                 binom(i - 1, i / 2) % MOD) %
                  MOD;
        vertical = (vertical +
                    binom(N + M - 1 - i, N - i / 2 - 1) * binom(i - 1, i / 2)) %
                   MOD;
      } else {
        horizon = (horizon - binom(N + M - 1 - i, M - i / 2 - 1) *
                                 binom(i - 1, i / 2) % MOD) %
                  MOD;
        vertical = (vertical - binom(N + M - 1 - i, N - i / 2 - 1) *
                                   binom(i - 1, i / 2) % MOD) %
                   MOD;
      }
    }
    if (i >= N * 2)
      vertical = 0;
    // if (i >= M && M > 1) horizon = (horizon - binom((i - M) + M - 1, M - 1))
    // % MOD; if (i >= N && i < N * 2 && N > 1) vertical = (vertical - binom((i
    // - N) + N - 1, N - 1)) % MOD;
  }

  i64 result = 0;
  for (int i = 1; i <= N + M; ++i)
    result = (result + res[i] * inv[i] % MOD) % MOD;
  result = result * fac[N] % MOD * fac[M] % MOD * ifac[N + M] % MOD;
  printf("%lld\n", (result + MOD) % MOD);
  return 0;
}