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

#pragma GCC target("avx2")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("O3")
#include "bits/stdc++.h"
#include <random>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long long ll;
const ll MOD = 1'000'000'007LL; /*998'244'353LL;*/
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

int N, A, B;

int dp[5001][5001][2][2];
int dp1[5002][5002][2];
int dp2[5002][5002][2];

signed main() {
  cin >> N >> A >> B;
  if (A < B)
    swap(A, B);
  for (short n = N; n >= 0; n--) {
    for (short k = N; k >= 0; k--) {
      for (short b = 0; b < 2; b++) {
        for (short a = 0; a < 2; a++) {
          if (n == N) {
            if (a == 1 || k >= A)
              dp[n][k][b][a] = 1;
            else
              dp[n][k][b][a] = 0;
            continue;
          }
          bool a2 = a;
          if (k >= A)
            a2 = true;
          ll ret = dp[n + 1][k + 1][0][a2];
          if (b == 0) {
            ret += dp1[n + 1][0][a2] - dp1[n + min(B, N - n + 1)][0][a2];
            ret += dp2[n + min(B, N - n + 1)][k + min(B, N - n + 1)][a2] -
                   dp2[N + 1][k + N - n + 1][a2];
          }
          if (ret < 0)
            ret += MOD;
          if (ret < 0)
            ret += MOD;
          if (ret >= MOD)
            ret -= MOD;
          if (ret >= MOD)
            ret -= MOD;
          dp[n][k][b][a] = ret;
        }
      }

      for (short a = 0; a < 2; a++) {
        int ret = dp[n][k][1][a] + dp1[n + 1][k][a];
        if (ret >= MOD)
          ret -= MOD;
        dp1[n][k][a] = ret;
      }

      for (short a = 0; a < 2; a++) {
        int ret = dp[n][k][1][a] + dp2[n + 1][k + 1][a];
        if (ret >= MOD)
          ret -= MOD;
        dp2[n][k][a] = ret;
      }
    }
  }
  cout << dp[0][0][0][0] << endl;
}

Error: TLE

Fixed submission:

#pragma GCC target("avx2")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("O3")
#include "bits/stdc++.h"
#include <random>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long long ll;
const ll MOD = 1'000'000'007LL; /*998'244'353LL;*/
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

int N, A, B;

bool vis[5001][5001][2][2];
int dp[5001][5001][2][2];

int sum1(short, short, bool, bool);
int sum2(short, short, bool, bool);

int solve(short n, short k, bool b, bool a) {
  if (n == N) {
    if (a == 1 || k >= A)
      return 1;
    else
      return 0;
  }
  if (vis[n][k][b][a])
    return dp[n][k][b][a];
  vis[n][k][b][a] = true;
  bool a2 = a;
  if (k >= A)
    a2 = true;
  ll ret = solve(n + 1, k + 1, 0, a2);
  if (b == 0) {
    ret += sum1(n + 1, 0, 1, a2) - sum1(n + min(B, N - n + 1), 0, 1, a2);
    ret += sum2(n + min(B, N - n + 1), k + min(B, N - n + 1), 1, a2) -
           sum2(N + 1, k + N - n + 1, 1, a2);
  }
  if (ret < 0)
    ret += MOD;
  if (ret < 0)
    ret += MOD;
  if (ret >= MOD)
    ret -= MOD;
  if (ret >= MOD)
    ret -= MOD;
  return dp[n][k][b][a] = ret;
}

bool vis1[2][5001][5001];
int dp1[2][5001][5001];
int sum1(short n, short k, bool b, bool a) {
  if (n > N)
    return 0;
  if (vis1[a][n][k])
    return dp1[a][n][k];
  vis1[a][n][k] = true;
  int ret = solve(n, k, b, a) + sum1(n + 1, k, b, a);
  if (ret >= MOD)
    ret -= MOD;
  return dp1[a][n][k] = ret;
}

bool vis2[2][5001][5001];
int dp2[2][5001][5001];
int sum2(short n, short k, bool b, bool a) {
  if (n > N)
    return 0;
  if (vis2[a][n][k])
    return dp2[a][n][k];
  vis2[a][n][k] = true;
  int ret = solve(n, k, b, a) + sum2(n + 1, k + 1, b, a);
  if (ret >= MOD)
    ret -= MOD;
  return dp2[a][n][k] = ret;
}

signed main() {
  cin >> N >> A >> B;
  if (A < B)
    swap(A, B);
  cout << solve(0, 0, 0, 0) << endl;
}