Problem p02653 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <chrono>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_set>
#include <vector>
using namespace std;
using namespace std::chrono;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
#define REP(i, n) for (int i = 0; i < (n); i++)
/*cout<<fixed<<setprecision(20);cin.tie(0);ios::sync_with_stdio(false);*/
const llint mod = 1000000007;
const llint inf = 2.19e15 + 1;
const long double pai = 3.141592653589793238462643383279502884197;
const long double eps = 1e-10;
template <class T, class U> bool chmin(T &a, U b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T, class U> bool chmax(T &a, U b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
llint gcd(llint a, llint b) {
  if (a % b == 0) {
    return b;
  } else
    return gcd(b, a % b);
}
llint lcm(llint a, llint b) {
  if (a == 0) {
    return b;
  }
  return a / gcd(a, b) * b;
}
template <class T> void SO(T &ve) { sort(ve.begin(), ve.end()); }
template <class T> void REV(T &ve) { reverse(ve.begin(), ve.end()); }
template <class T> llint LBI(const vector<T> &ar, T in) {
  return lower_bound(ar.begin(), ar.end(), in) - ar.begin();
}
template <class T> llint UBI(const vector<T> &ar, T in) {
  return upper_bound(ar.begin(), ar.end(), in) - ar.begin();
}

#include <algorithm>
#include <cstdint>
#include <type_traits>
#include <utility>
// 永夜作
#define mnt mint_base
class mint_base;
// mint_base_base型用の累乗関数
constexpr mint_base m_pow(mint_base x, uint64_t n) noexcept;
// mod計算を自動で行う整数テンプレートクラス
class mint_base {
public:
  constexpr mint_base operator+(const mint_base &other) const noexcept {
    auto v = *this;
    return v += other;
  }
  constexpr mint_base operator-(const mint_base &other) const noexcept {
    auto v = *this;
    return v -= other;
  }
  constexpr mint_base operator*(const mint_base &other) const noexcept {
    auto v = *this;
    return v *= other;
  }
  constexpr auto operator/(const mint_base &other) const noexcept {
    auto v = *this;
    return v /= other;
  }
  constexpr mint_base &operator+=(const mint_base &other) noexcept {
    a += other.a;
    if (mod <= a) {
      a -= mod;
    };
    return *this;
  }
  constexpr mint_base &operator-=(const mint_base &other) noexcept {
    if (a >= other.a) {
      a -= other.a;
    } else {
      a = (a + mod) - other.a;
    }
    return *this;
  }
  constexpr mint_base &operator*=(const mint_base &other) noexcept {
    a *= other.a;
    a %= mod;
    return *this;
  }
  constexpr mint_base &operator/=(const mint_base &other) noexcept {
    return *this *= ~other;
  }
  constexpr mint_base operator+() const noexcept { return *this; }
  constexpr mint_base operator-() const noexcept {
    return {mod - a, mod_value_tag{}};
  }
  constexpr mint_base &operator++() noexcept {
    if (mod <= ++a) {
      a = 0;
    };
    return *this;
  }
  constexpr mint_base &operator--() noexcept {
    if (a <= 0) {
      a = mod;
    };
    --a;
    return *this;
  }
  constexpr mint_base operator++(int) noexcept {
    auto tmp = *this;
    ++*this;
    return tmp;
  }
  constexpr mint_base operator--(int) noexcept {
    auto tmp = *this;
    --*this;
    return tmp;
  }
  constexpr mint_base operator~() const noexcept {
    return m_pow(*this, mod - 2);
  }
  constexpr mint_base &operator=(const mint_base &other) noexcept {
    a = other.a;
    return *this;
  }
  constexpr explicit operator uint64_t() const noexcept { return a; }
  constexpr explicit operator int() const noexcept { return a; }
  constexpr explicit operator unsigned() const noexcept { return (unsigned)a; }
  static constexpr uint64_t getmod() noexcept { return mod; }
  constexpr mint_base(uint64_t a_) noexcept : a(a_ % mod) {}
  constexpr mint_base() noexcept : a(0) {}
  struct mod_value_tag {};
  constexpr mint_base(uint64_t a_, mod_value_tag) : a(a_) {}

private:
  uint64_t a;
};

// mint_base型用の累乗関数
constexpr mint_base m_pow(mint_base x, uint64_t n) noexcept {
  mint_base res = 1;
  while (n > 0) {
    if (n & 1) {
      res *= x;
    }
    x *= x;
    n >>= 1;
  }
  return res;
}
// mint_baseの階乗計算
// 0からxまでの階乗を返す
// O(x)時間が必要
vector<mint_base> fla; // 階乗が入る
void fla_set(mint_base x) {
  fla.resize(((uint64_t)x) + 1);
  fla[0] = 1;
  for (uint64_t i = 1; i <= (uint64_t)x; i++) {
    fla[i] = fla[i - 1] * i;
  }
}
vector<mint_base> gya; //~fla[i] が入る

// O(x+log mod)で求める O(xlogmod)より速い
void fla_gya_set(mint_base x) {
  fla_set(x);
  gya.resize(((uint64_t)x) + 1);
  gya[(uint64_t)x] = ~fla[(uint64_t)x];
  for (uint64_t i = (uint64_t)x; i > 0; i--) {
    gya[i - 1] = gya[i] * i;
  }
}

// mint_base型のstreamへの出力
std::ostream &operator<<(std::ostream &os, mint_base i) {
  os << (uint64_t)i;
  return os;
}
// mint_base型のstreamからの入力
std::istream &operator>>(std::istream &is, mint_base &i) {
  uint64_t tmp;
  is >> tmp;
  i = tmp;
  return is;
}

int main(void) {
  int i, j, k, n, A, B;
  cin >> n >> A >> B;
  if (A > B) {
    swap(A, B);
  }

  // できない数をカウントする

  static mint_base dp[5015][5015] = {};
  static mint_base ep[5015][5015] = {};
  mint_base wa[5015] = {};
  mint_base ans = 0;
  dp[0][0] = 1;
  for (i = 0; i <= n; i++) {
    mint_base aaa = 0;
    wa[i + 1] += wa[i];
    dp[i][1] += wa[i];
    for (j = 0; j < B; j++) {

      dp[i][j] += ep[i][j];
      // cout<<dp[i][j]<<" ";
      ep[i + 1][j + 1] += ep[i][j];
      dp[i + 1][j + 1] += dp[i][j]; // 1
      if (i > 0 && j == 0) {
        continue;
      }
      aaa += dp[i][j];
      if (i + A + 1 <= n + 5 && j + A + 1 <= n + 5) {
        ep[i + A + 1][j + A + 1] += dp[i][j];
      }
    }
    // cout<<endl;
    // cout<<aaa<<endl;
    wa[i + 2] += aaa;
    wa[i + A + 1] -= aaa;
  }
  for (i = 0; i <= n; i++) {
    for (j = 0; j < B; j++) {
      if (n - i + j < B || n - i < A) {
        ans += dp[i][j];
      }
    }
  }
  mint_base eee = 1;
  for (i = 0; i < n; i++) {
    eee *= 2;
  }
  cout << eee - ans << endl;
  return 0;
}


Fixed submission:
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <chrono>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_set>
#include <vector>
using namespace std;
using namespace std::chrono;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
#define REP(i, n) for (int i = 0; i < (n); i++)
/*cout<<fixed<<setprecision(20);cin.tie(0);ios::sync_with_stdio(false);*/
const llint mod = 1000000007;
const llint inf = 2.19e15 + 1;
const long double pai = 3.141592653589793238462643383279502884197;
const long double eps = 1e-10;
template <class T, class U> bool chmin(T &a, U b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T, class U> bool chmax(T &a, U b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
llint gcd(llint a, llint b) {
  if (a % b == 0) {
    return b;
  } else
    return gcd(b, a % b);
}
llint lcm(llint a, llint b) {
  if (a == 0) {
    return b;
  }
  return a / gcd(a, b) * b;
}
template <class T> void SO(T &ve) { sort(ve.begin(), ve.end()); }
template <class T> void REV(T &ve) { reverse(ve.begin(), ve.end()); }
template <class T> llint LBI(const vector<T> &ar, T in) {
  return lower_bound(ar.begin(), ar.end(), in) - ar.begin();
}
template <class T> llint UBI(const vector<T> &ar, T in) {
  return upper_bound(ar.begin(), ar.end(), in) - ar.begin();
}

#include <algorithm>
#include <cstdint>
#include <type_traits>
#include <utility>
// 永夜作
#define mnt mint_base
class mint_base;
// mint_base_base型用の累乗関数
constexpr mint_base m_pow(mint_base x, uint64_t n) noexcept;
// mod計算を自動で行う整数テンプレートクラス
class mint_base {
public:
  constexpr mint_base operator+(const mint_base &other) const noexcept {
    auto v = *this;
    return v += other;
  }
  constexpr mint_base operator-(const mint_base &other) const noexcept {
    auto v = *this;
    return v -= other;
  }
  constexpr mint_base operator*(const mint_base &other) const noexcept {
    auto v = *this;
    return v *= other;
  }
  constexpr auto operator/(const mint_base &other) const noexcept {
    auto v = *this;
    return v /= other;
  }
  constexpr mint_base &operator+=(const mint_base &other) noexcept {
    a += other.a;
    if (mod <= a) {
      a -= mod;
    };
    return *this;
  }
  constexpr mint_base &operator-=(const mint_base &other) noexcept {
    if (a >= other.a) {
      a -= other.a;
    } else {
      a = (a + mod) - other.a;
    }
    return *this;
  }
  constexpr mint_base &operator*=(const mint_base &other) noexcept {
    a *= other.a;
    a %= mod;
    return *this;
  }
  constexpr mint_base &operator/=(const mint_base &other) noexcept {
    return *this *= ~other;
  }
  constexpr mint_base operator+() const noexcept { return *this; }
  constexpr mint_base operator-() const noexcept {
    return {mod - a, mod_value_tag{}};
  }
  constexpr mint_base &operator++() noexcept {
    if (mod <= ++a) {
      a = 0;
    };
    return *this;
  }
  constexpr mint_base &operator--() noexcept {
    if (a <= 0) {
      a = mod;
    };
    --a;
    return *this;
  }
  constexpr mint_base operator++(int) noexcept {
    auto tmp = *this;
    ++*this;
    return tmp;
  }
  constexpr mint_base operator--(int) noexcept {
    auto tmp = *this;
    --*this;
    return tmp;
  }
  constexpr mint_base operator~() const noexcept {
    return m_pow(*this, mod - 2);
  }
  constexpr mint_base &operator=(const mint_base &other) noexcept {
    a = other.a;
    return *this;
  }
  constexpr explicit operator uint64_t() const noexcept { return a; }
  constexpr explicit operator int() const noexcept { return a; }
  constexpr explicit operator unsigned() const noexcept { return (unsigned)a; }
  static constexpr uint64_t getmod() noexcept { return mod; }
  constexpr mint_base(uint64_t a_) noexcept : a(a_ % mod) {}
  constexpr mint_base() noexcept : a(0) {}
  struct mod_value_tag {};
  constexpr mint_base(uint64_t a_, mod_value_tag) : a(a_) {}

private:
  uint64_t a;
};

// mint_base型用の累乗関数
constexpr mint_base m_pow(mint_base x, uint64_t n) noexcept {
  mint_base res = 1;
  while (n > 0) {
    if (n & 1) {
      res *= x;
    }
    x *= x;
    n >>= 1;
  }
  return res;
}
// mint_baseの階乗計算
// 0からxまでの階乗を返す
// O(x)時間が必要
vector<mint_base> fla; // 階乗が入る
void fla_set(mint_base x) {
  fla.resize(((uint64_t)x) + 1);
  fla[0] = 1;
  for (uint64_t i = 1; i <= (uint64_t)x; i++) {
    fla[i] = fla[i - 1] * i;
  }
}
vector<mint_base> gya; //~fla[i] が入る

// O(x+log mod)で求める O(xlogmod)より速い
void fla_gya_set(mint_base x) {
  fla_set(x);
  gya.resize(((uint64_t)x) + 1);
  gya[(uint64_t)x] = ~fla[(uint64_t)x];
  for (uint64_t i = (uint64_t)x; i > 0; i--) {
    gya[i - 1] = gya[i] * i;
  }
}

// mint_base型のstreamへの出力
std::ostream &operator<<(std::ostream &os, mint_base i) {
  os << (uint64_t)i;
  return os;
}
// mint_base型のstreamからの入力
std::istream &operator>>(std::istream &is, mint_base &i) {
  uint64_t tmp;
  is >> tmp;
  i = tmp;
  return is;
}

int main(void) {
  int i, j, k, n, A, B;
  cin >> n >> A >> B;
  if (A > B) {
    swap(A, B);
  }

  // できない数をカウントする

  static mint_base dp[5015][5015] = {};
  static mint_base ep[5015][5015] = {};
  mint_base wa[5015] = {};
  mint_base ans = 0;
  dp[0][0] = 1;
  for (i = 0; i <= n; i++) {
    mint_base aaa = 0;
    wa[i + 1] += wa[i];
    dp[i][1] += wa[i];
    for (j = 0; j < B; j++) {

      dp[i][j] += ep[i][j];
      // cout<<dp[i][j]<<" ";
      ep[i + 1][j + 1] += ep[i][j];
      dp[i + 1][j + 1] += dp[i][j]; // 1
      if (i > 0 && j == 0) {
        continue;
      }
      aaa += dp[i][j];
      if (i + A + 1 <= n + 5 && j + A + 1 <= n + 5) {
        ep[i + A + 1][j + A + 1] += dp[i][j];
      }
    }
    // cout<<endl;
    // cout<<aaa<<endl;
    wa[i + 2] += aaa;
    if (i + A + 1 <= n + 5) {
      wa[i + A + 1] -= aaa;
    }
  }
  for (i = 0; i <= n; i++) {
    for (j = 0; j < B; j++) {
      if (n - i + j < B || n - i < A) {
        ans += dp[i][j];
      }
    }
  }
  mint_base eee = 1;
  for (i = 0; i < n; i++) {
    eee *= 2;
  }
  cout << eee - ans << endl;
  return 0;
}