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

// =========== Template ========== //
#include <bits/stdc++.h>
using namespace std;
int fastio() {
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  cin.tie(nullptr);
  return 0;
}
int __fastio = fastio();
template <typename A, typename B>
ostream &operator<<(ostream &os, const pair<A, B> &p);
template <typename A> ostream &operator<<(ostream &os, const set<A> &m) {
  os << "{";
  string sep = "";
  for (auto e : m)
    os << sep << e, sep = ", ";
  return os << "}";
}
template <typename A> ostream &operator<<(ostream &os, const multiset<A> &m) {
  os << "{";
  string sep = "";
  for (auto e : m)
    os << sep << e, sep = ", ";
  return os << "}";
}
template <typename A, typename B>
ostream &operator<<(ostream &os, const map<A, B> &m) {
  os << "{";
  string sep = "";
  for (auto e : m)
    os << sep << e.first << ": " << e.second, sep = ", ";
  return os << "}";
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  string sep = "";
  for (auto e : v)
    os << sep << e, sep = ", ";
  return os << "]";
}
template <typename A, typename B>
ostream &operator<<(ostream &os, const pair<A, B> &p) {
  os << '(' << p.first << ", " << p.second << ')';
  return os;
}
void dbg_out() { cerr << endl; }
template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) {
  cerr << ' ' << H;
  dbg_out(T...);
}
#ifdef STEVEN
#define pp(...) cerr << "\\t[" << #__VA_ARGS__ << "]:\\t", dbg_out(__VA_ARGS__)
#define ppp(x) cerr << x << "\\n"
#else
#define pp(...)
#define ppp(...)
#endif
template <class Fun> class y_combinator_result {
  Fun fun_;

public:
  template <class T>
  explicit y_combinator_result(T &&fun) : fun_(std::forward<T>(fun)) {}
  template <class... Args> decltype(auto) operator()(Args &&...args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }
};
template <class Fun> decltype(auto) y_combinator(Fun &&fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
#define fi first
#define se second
#define sz(x) (int((x).size()))
#define data _data
// =========== Book ============ //

const int inf = 1000 << 20;
const ll infl = 1LL << 60;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template <int MOD_> struct modnum {
  static constexpr int MOD = MOD_;
  static_assert(MOD_ > 0, "MOD must be positive");

private:
  using ll = long long;
  int v;
  static int minv(int a, int m) {
    a %= m;
    assert(a);
    return a == 1 ? 1 : int(m - ll(minv(m, a)) * ll(m) / a);
  }

public:
  modnum() : v(0) {}
  modnum(ll v_) : v(int(v_ % MOD)) {
    if (v < 0)
      v += MOD;
  }
  explicit operator int() const { return v; }
  friend std::ostream &operator<<(std::ostream &out, const modnum &n) {
    return out << int(n);
  }
  friend std::istream &operator>>(std::istream &in, modnum &n) {
    ll v_;
    in >> v_;
    n = modnum(v_);
    return in;
  }
  friend bool operator==(const modnum &a, const modnum &b) {
    return a.v == b.v;
  }
  friend bool operator!=(const modnum &a, const modnum &b) {
    return a.v != b.v;
  }
  modnum inv() const {
    modnum res;
    res.v = minv(v, MOD);
    return res;
  }
  friend modnum inv(const modnum &m) { return m.inv(); }
  modnum neg() const {
    modnum res;
    res.v = v ? MOD - v : 0;
    return res;
  }
  friend modnum neg(const modnum &m) { return m.neg(); }
  modnum operator-() const { return neg(); }
  modnum operator+() const { return modnum(*this); }
  modnum &operator++() {
    v++;
    if (v == MOD)
      v = 0;
    return *this;
  }
  modnum &operator--() {
    if (v == 0)
      v = MOD;
    v--;
    return *this;
  }
  modnum &operator+=(const modnum &o) {
    v += o.v;
    if (v >= MOD)
      v -= MOD;
    return *this;
  }
  modnum &operator-=(const modnum &o) {
    v -= o.v;
    if (v < 0)
      v += MOD;
    return *this;
  }
  modnum &operator*=(const modnum &o) {
    v = int(ll(v) * ll(o.v) % MOD);
    return *this;
  }
  modnum &operator/=(const modnum &o) { return *this *= o.inv(); }
  friend modnum operator++(modnum &a, int) {
    modnum r = a;
    ++a;
    return r;
  }
  friend modnum operator--(modnum &a, int) {
    modnum r = a;
    --a;
    return r;
  }
  friend modnum operator+(const modnum &a, const modnum &b) {
    return modnum(a) += b;
  }
  friend modnum operator-(const modnum &a, const modnum &b) {
    return modnum(a) -= b;
  }
  friend modnum operator*(const modnum &a, const modnum &b) {
    return modnum(a) *= b;
  }
  friend modnum operator/(const modnum &a, const modnum &b) {
    return modnum(a) /= b;
  }
};

// ============= Solution ============= //

// state: len, cnt, last
// last = 1 ->
//   len + 1, cnt + 1, 1
//   len + 1, cnt + 1, 0
// last = 0 ->
//   len + A, cnt + A, 1
//   len + 1, cnt + 1, 0
//   len + k + 1, 1, 0 for k = 1...A - 1

typedef modnum<int(1E9 + 7)> mint;
mint dp[5010][5010][2];
int main() {
  int n, a, b;
  cin >> n >> a >> b;
  if (a > b)
    swap(a, b);
  for (int i = 0; i < b; ++i) {
    for (int j = 0; j < 2; ++j) {
      dp[n][i][j] = 1;
    }
  }

  for (int i = n - 1; i >= 0; --i) {
    mint val = 0;
    for (int c = 1; c <= a - 1; ++c) {
      if (i + c + 1 <= n) {
        val += dp[i + c + 1][1][0];
      }
    }
    if (n - i < a) {
      val += dp[n][1][0];
    }

    for (int j = 0; j < b; ++j) {
      for (int k = 0; k < 2; ++k) {
        if (k == 1) {
          if (j + 1 < b) {
            dp[i][j][k] += dp[i + 1][j + 1][1];
            dp[i][j][k] += dp[i + 1][j + 1][0];
          }
        } else {
          if (i + a <= n && j + a < b) {
            dp[i][j][k] += dp[i + a][j + a][1];
          }
          if (j + 1 < b) {
            dp[i][j][k] += dp[i + 1][j + 1][0];
          }
          dp[i][j][k] += val;
        }
      }
    }
  }
  mint ans = 1;
  for (int i = 0; i < n; ++i)
    ans *= 2;
  ans -= dp[0][0][0];
  cout << ans << "\\n";
}

// ============== Notes =============== //
// common bugs
// - fastio
// - int overflow (especially intermediate expressionns)
// - array bounds (indices bigger than MAXN?)
// - special cases (n=1? graph not connected?)
// - re-initialize efficiently between test cases


Error: TLE

Fixed submission:

// =========== Template ========== //
#include <bits/stdc++.h>
using namespace std;
int fastio() {
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  cin.tie(nullptr);
  return 0;
}
int __fastio = fastio();
template <typename A, typename B>
ostream &operator<<(ostream &os, const pair<A, B> &p);
template <typename A> ostream &operator<<(ostream &os, const set<A> &m) {
  os << "{";
  string sep = "";
  for (auto e : m)
    os << sep << e, sep = ", ";
  return os << "}";
}
template <typename A> ostream &operator<<(ostream &os, const multiset<A> &m) {
  os << "{";
  string sep = "";
  for (auto e : m)
    os << sep << e, sep = ", ";
  return os << "}";
}
template <typename A, typename B>
ostream &operator<<(ostream &os, const map<A, B> &m) {
  os << "{";
  string sep = "";
  for (auto e : m)
    os << sep << e.first << ": " << e.second, sep = ", ";
  return os << "}";
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  string sep = "";
  for (auto e : v)
    os << sep << e, sep = ", ";
  return os << "]";
}
template <typename A, typename B>
ostream &operator<<(ostream &os, const pair<A, B> &p) {
  os << '(' << p.first << ", " << p.second << ')';
  return os;
}
void dbg_out() { cerr << endl; }
template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) {
  cerr << ' ' << H;
  dbg_out(T...);
}
#ifdef STEVEN
#define pp(...) cerr << "\\t[" << #__VA_ARGS__ << "]:\\t", dbg_out(__VA_ARGS__)
#define ppp(x) cerr << x << "\\n"
#else
#define pp(...)
#define ppp(...)
#endif
template <class Fun> class y_combinator_result {
  Fun fun_;

public:
  template <class T>
  explicit y_combinator_result(T &&fun) : fun_(std::forward<T>(fun)) {}
  template <class... Args> decltype(auto) operator()(Args &&...args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }
};
template <class Fun> decltype(auto) y_combinator(Fun &&fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
#define fi first
#define se second
#define sz(x) (int((x).size()))
#define data _data
// =========== Book ============ //

const int inf = 1000 << 20;
const ll infl = 1LL << 60;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template <int MOD_> struct modnum {
  static constexpr int MOD = MOD_;
  static_assert(MOD_ > 0, "MOD must be positive");

private:
  using ll = long long;
  int v;
  static int minv(int a, int m) {
    a %= m;
    assert(a);
    return a == 1 ? 1 : int(m - ll(minv(m, a)) * ll(m) / a);
  }

public:
  modnum() : v(0) {}
  modnum(ll v_) : v(int(v_ % MOD)) {
    if (v < 0)
      v += MOD;
  }
  explicit operator int() const { return v; }
  friend std::ostream &operator<<(std::ostream &out, const modnum &n) {
    return out << int(n);
  }
  friend std::istream &operator>>(std::istream &in, modnum &n) {
    ll v_;
    in >> v_;
    n = modnum(v_);
    return in;
  }
  friend bool operator==(const modnum &a, const modnum &b) {
    return a.v == b.v;
  }
  friend bool operator!=(const modnum &a, const modnum &b) {
    return a.v != b.v;
  }
  modnum inv() const {
    modnum res;
    res.v = minv(v, MOD);
    return res;
  }
  friend modnum inv(const modnum &m) { return m.inv(); }
  modnum neg() const {
    modnum res;
    res.v = v ? MOD - v : 0;
    return res;
  }
  friend modnum neg(const modnum &m) { return m.neg(); }
  modnum operator-() const { return neg(); }
  modnum operator+() const { return modnum(*this); }
  modnum &operator++() {
    v++;
    if (v == MOD)
      v = 0;
    return *this;
  }
  modnum &operator--() {
    if (v == 0)
      v = MOD;
    v--;
    return *this;
  }
  modnum &operator+=(const modnum &o) {
    v += o.v;
    if (v >= MOD)
      v -= MOD;
    return *this;
  }
  modnum &operator-=(const modnum &o) {
    v -= o.v;
    if (v < 0)
      v += MOD;
    return *this;
  }
  modnum &operator*=(const modnum &o) {
    v = int(ll(v) * ll(o.v) % MOD);
    return *this;
  }
  modnum &operator/=(const modnum &o) { return *this *= o.inv(); }
  friend modnum operator++(modnum &a, int) {
    modnum r = a;
    ++a;
    return r;
  }
  friend modnum operator--(modnum &a, int) {
    modnum r = a;
    --a;
    return r;
  }
  friend modnum operator+(const modnum &a, const modnum &b) {
    return modnum(a) += b;
  }
  friend modnum operator-(const modnum &a, const modnum &b) {
    return modnum(a) -= b;
  }
  friend modnum operator*(const modnum &a, const modnum &b) {
    return modnum(a) *= b;
  }
  friend modnum operator/(const modnum &a, const modnum &b) {
    return modnum(a) /= b;
  }
};

// ============= Solution ============= //

// state: len, cnt, last
// last = 1 ->
//   len + 1, cnt + 1, 1
//   len + 1, cnt + 1, 0
// last = 0 ->
//   len + A, cnt + A, 1
//   len + 1, cnt + 1, 0
//   len + k + 1, 1, 0 for k = 1...A - 1

typedef modnum<int(1E9 + 7)> mint;
int main() {
  int n, a, b;
  cin >> n >> a >> b;
  if (a > b)
    swap(a, b);
  vector<vector<vector<mint>>> dp(n + 1,
                                  vector<vector<mint>>(b + 1, vector<mint>(2)));
  for (int i = 0; i < b; ++i) {
    for (int j = 0; j < 2; ++j) {
      dp[n][i][j] = 1;
    }
  }

  for (int i = n - 1; i >= 0; --i) {
    mint val = 0;
    for (int c = 1; c <= a - 1; ++c) {
      if (i + c + 1 <= n) {
        val += dp[i + c + 1][1][0];
      }
    }
    if (n - i < a) {
      val += dp[n][1][0];
    }

    for (int j = 0; j < b; ++j) {
      for (int k = 0; k < 2; ++k) {
        if (k == 1) {
          if (j + 1 < b) {
            dp[i][j][k] += dp[i + 1][j + 1][1];
            dp[i][j][k] += dp[i + 1][j + 1][0];
          }
        } else {
          if (i + a <= n && j + a < b) {
            dp[i][j][k] += dp[i + a][j + a][1];
          }
          if (j + 1 < b) {
            dp[i][j][k] += dp[i + 1][j + 1][0];
          }
          dp[i][j][k] += val;
        }
      }
    }
  }
  mint ans = 1;
  for (int i = 0; i < n; ++i)
    ans *= 2;
  ans -= dp[0][0][0];
  cout << ans << "\\n";
}

// ============== Notes =============== //
// common bugs
// - fastio
// - int overflow (especially intermediate expressionns)
// - array bounds (indices bigger than MAXN?)
// - special cases (n=1? graph not connected?)
// - re-initialize efficiently between test cases