Problem p01452 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

const int MOD = 1000000007;

long long inverse(long long a) {
  static vector<int> memo(300001, -1);
  if (memo[a] != -1)
    return memo[a];

  int b = MOD - 2;
  long long c = a;
  long long ret = 1;
  while (b > 0) {
    if (b & 1) {
      ret *= c;
      ret %= MOD;
    }
    c *= c;
    c %= MOD;
    b >>= 1;
  }

  return memo[a] = ret;
}

long long comb(int n, int m) {
  static vector<long long> a(300001, -1), b(300001, -1);
  if (a[1] == -1) {
    a[1] = b[1] = 1;
    for (int i = 2; i <= 300000; ++i) {
      a[i] = a[i - 1] * i;
      a[i] %= MOD;
      b[i] = b[i - 1] * inverse(i);
      b[i] %= MOD;
    }
  }

  if (m < 0 || m > n)
    return 0;
  if (m == 0 || m == n)
    return 1;

  return ((a[n] * b[m]) % MOD * b[n - m]) % MOD;
}

vector<long long> solve(int len, int n) {
  vector<long long> ret(n + 1);
  ret[0] = 1;
  long long tmp = 1;
  for (int i = 1; i <= n; ++i) {
    ret[i] = comb(len + 2 * i, i) - comb(len + 2 * i, i - 1);
    ret[i] += MOD;
    ret[i] %= MOD;
  }

  return ret;
}

int main() {
  int w, h, n; // ゴールのx座標、y座標、寄り道回数
  cin >> w >> h >> n;

  vector<long long> s = solve(w, n);
  vector<long long> t = solve(h, n);

  long long ret = 0;
  for (int i = 0; i <= n; ++i) {
    ret += (s[n - i] * t[i]) % MOD * comb(w + h + 2 * n, h + 2 * i);
    ret %= MOD;
  }
  cout << ret << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

const int MOD = 1000000007;

long long inverse(long long a) {
  static vector<int> memo(300000, -1);
  if (memo[a] != -1)
    return memo[a];

  int b = MOD - 2;
  long long c = a;
  long long ret = 1;
  while (b > 0) {
    if (b & 1) {
      ret *= c;
      ret %= MOD;
    }
    c *= c;
    c %= MOD;
    b >>= 1;
  }

  return memo[a] = ret;
}

vector<long long> solve(int len, int n) {
  if (len < n) {
    vector<long long> ret;
    vector<long long> curr(2 * n + 1, 0);
    curr[0] = 1;
    for (int i = 0; i <= n; ++i) {
      vector<long long> next(2 * n + 1, 0);
      for (int j = 0; j < 2 * n; ++j) {
        (curr[j + 1] += curr[j]) %= MOD;
        if (j - 1 >= 0)
          (next[j - 1] += curr[j]) %= MOD;
      }
      ret.push_back(curr[len]);
      curr.swap(next);
    }
    return ret;
  }

  vector<long long> dp;
  vector<long long> curr(n + 1, 0);
  curr[0] = 1;
  for (int i = 0; i <= n; ++i) {
    vector<long long> next(n + 1, 0);
    for (int j = 0; j < n; ++j) {
      (curr[j + 1] += curr[j]) %= MOD;
      if (j - 1 >= 0)
        (next[j - 1] += curr[j]) %= MOD;
    }
    dp.push_back(curr[n]);
    curr.swap(next);
  }

  vector<long long> ret(n + 1, 0);
  for (int i = 0; i <= n; ++i) {
    long long tmp = 1;
    for (int j = 0; j < i; ++j) {
      tmp *= len - n + 2 * i - j;
      tmp %= MOD;
      tmp *= inverse(j + 1);
      tmp %= MOD;
    }

    for (int j = 0; j <= n - i; ++j) {
      ret[i + j] += dp[j] * tmp;
      ret[i + j] %= MOD;
    }
  }
  return ret;
}

int main() {
  int w, h, n; // ゴールのx座標、y座標、寄り道回数
  cin >> w >> h >> n;

  vector<long long> s = solve(w, n);
  vector<long long> t = solve(h, n);

  long long tmp = 1;
  for (int i = 0; i < h; ++i) {
    tmp *= w + h + 2 * n - i;
    tmp %= MOD;
    tmp *= inverse(i + 1);
    tmp %= MOD;
  }

  long long ret = 0;
  for (int i = 0; i <= n; ++i) {
    ret += (s[n - i] * t[i]) % MOD * tmp;
    ret %= MOD;

    for (int j = 0; j < 2; ++j) {
      tmp *= w + 2 * n - 2 * i - j;
      tmp %= MOD;
      tmp *= inverse(h + 1 + 2 * i + j);
      tmp %= MOD;
    }
  }
  cout << ret << endl;

  return 0;
}