Problem p02653 (C++) — buggy submission, verdict: Runtime Error


#if 1
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

auto &in = std::cin;
auto &out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const double PI =
    3.141592653589793238462643383279502884197169399375105820974944;

template <typename Arithmetic, typename Integral>
std::enable_if_t<std::is_unsigned<Integral>::value, Arithmetic>
ipow(Arithmetic bace, Integral n) {
  // 繰り返し二条法
  auto res = (Arithmetic)(1);
  while (n > 0) {
    if (n & 1)
      res *= bace;
    bace *= bace;
    n >>= 1;
  }
  return res;
}
constexpr bool is_prime(uint32_t N) {
  if (N <= 1) {
    return false;
  }
  for (size_t i = 2; i * i <= N; ++i) {
    if (N % i == 0) {
      return false;
    }
  }
  return true;
}
template <uint64_t MOD> class mint_base;
// mint_base_base型用の累乗関数
template <uint64_t MOD>
constexpr mint_base<MOD> m_pow(mint_base<MOD> x, uint64_t n) noexcept;
// mod計算を自動で行う整数テンプレートクラス
template <uint64_t MOD_ = 1000000007> class mint_base {
public:
  static constexpr auto MOD = MOD_;
  static_assert(!(MOD <= 2), "MOD cannot be below 2.");
  static_assert(MOD <= (0xFFFFFFFFFFFFFFFF / 2),
                "MOD is too big"); // 加算してオーバーフローしない
  static_assert(MOD <= 0xFFFFFFFF,
                "MOD is too big"); // 乗算してオーバーフローしない
  constexpr mint_base<MOD>
  operator+(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v += other;
  }
  constexpr mint_base<MOD>
  operator-(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v -= other;
  }
  constexpr mint_base<MOD>
  operator*(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v *= other;
  }
  constexpr auto operator/(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v /= other;
  }
  constexpr mint_base<MOD> &operator+=(const mint_base<MOD> &other) noexcept {
    a += other.a;
    if (MOD <= a) {
      a -= MOD;
    };
    return *this;
  }
  constexpr mint_base<MOD> &operator-=(const mint_base<MOD> &other) noexcept {
    if (a >= other.a) {
      a -= other.a;
    } else {
      a = (a + MOD) - other.a;
    }
    return *this;
  }
  constexpr mint_base<MOD> &operator*=(const mint_base<MOD> &other) noexcept {
#if 1
    a *= other.a;
    a %= MOD;
#else
    // MOD <= (MAXUINT64 / 2)条件下
    uint64_t b = other.a, v = 0;
    while (b > 0) {
      if (b & 1) {
        v += a;
        if (v >= MOD)
          v -= MOD;
      }
      a += a;
      if (MOD <= a)
        a -= MOD;
      b >>= 1;
    }
    a = v;
#endif
    return *this;
  }
  constexpr mint_base<MOD> &operator/=(const mint_base<MOD> &other) noexcept {
    return *this *= ~other;
  }
  constexpr mint_base<MOD> operator+() const noexcept { return *this; }
  constexpr mint_base<MOD> operator-() const noexcept {
    return {MOD - a, mod_value_tag{}};
  }
  constexpr mint_base<MOD> &operator++() noexcept {
    if (MOD <= ++a) {
      a = 0;
    };
    return *this;
  }
  constexpr mint_base<MOD> &operator--() noexcept {
    if (a <= 0) {
      a = MOD;
    };
    --a;
    return *this;
  }
  constexpr mint_base<MOD> operator++(int) noexcept {
    auto tmp = *this;
    ++*this;
    return tmp;
  }
  constexpr mint_base<MOD> operator--(int) noexcept {
    auto tmp = *this;
    --*this;
    return tmp;
  }
  constexpr mint_base<MOD> operator~() const noexcept {
    return ipow(*this, e_phi - 1);
  }
  constexpr mint_base<MOD> &operator=(const mint_base<MOD> &other) noexcept {
    a = other.a;
    return *this;
  }
  constexpr explicit operator uint64_t() 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:
  static constexpr uint64_t get_e_phi() noexcept {
    // オイラー値の導出
    uint64_t temp = MOD;
    uint64_t m_ = MOD;
    for (uint64_t i = 2; i * i <= m_; ++i) {
      if (m_ % i == 0) {
        temp = temp / i * (i - 1);
        for (; m_ % i == 0; m_ /= i)
          ;
      }
    }
    if (m_ != 1)
      temp = temp / m_ * (m_ - 1);
    return temp;
  }
  static constexpr uint64_t e_phi = get_e_phi(); // オイラー値
  uint64_t a;
};
// mint_base型用の累乗関数
template <uint64_t MOD>
constexpr mint_base<MOD> m_pow(mint_base<MOD> x, uint64_t n) noexcept {
  mint_base<MOD> res = 1;
  while (n > 0) {
    if (n & 1)
      res *= x;
    x *= x;
    n >>= 1;
  }
  return res;
}
// mint_baseの階乗計算
// O(x)時間が必要のため、fact_set関数を推奨する。
template <uint64_t MOD>
constexpr mint_base<MOD> fact(mint_base<MOD> x) noexcept {
  mint_base<MOD> res(1);
  for (uint64_t i = 1; i <= (uint64_t)x; ++i) {
    res *= i;
  }
  return res;
}
// mint_baseの階乗計算
// 0からxまでの階乗を返す
// O(x)時間が必要
template <uint64_t MOD>
std::vector<mint_base<MOD>> fact_set(mint_base<MOD> x = mint_base<MOD>(-1)) {
  mint_base<MOD> res(1);
  std::vector<mint_base<MOD>> set((uint64_t)(x) + 1);
  set[0] = 1;
  for (uint64_t i = 1; i <= (uint64_t)x; ++i) {
    res *= i;
    set[i] = res;
  }
  return res;
}
// mint_base型のstreamへの出力
template <uint64_t MOD>
std::ostream &operator<<(std::ostream &os, mint_base<MOD> i) {
  os << (uint64_t)i;
  return os;
}
// mint_base型のstreamからの入力
template <uint64_t MOD>
std::istream &operator>>(std::istream &is, mint_base<MOD> &i) {
  uint64_t tmp;
  is >> tmp;
  i = tmp;
  return is;
}
typedef mint_base<> mint;
namespace mint_literal {
constexpr mint operator""_mi(unsigned long long x) noexcept { return mint(x); }
} // namespace mint_literal
using namespace mint_literal;
// mint_baseの階乗計算
// 0からxまでの階乗を返す
// O(N)
template <int32_t X, uint64_t MOD = mint::MOD>
/*constexpr*/ std::array<mint_base<MOD>, X + 1> fact_set_c() {
  mint_base<MOD> res(1);
  std::array<mint_base<MOD>, X + 1> set;
  set[0] = 1;
  for (int32_t i = 1; i <= X; ++i) {
    res *= i;
    set[i] = res;
  }
  return set;
}

int32_t N, A, B;

mint dp1[5100][5100][2];
bool used1[5100][5100][2];
// mint func1(int i, int a_len, int fin)
//{
//	if (a_len >= A) {
//		fin = 1;
//	}
//	if (fin != 0) {
//		a_len = 0;
//	}
//	if (i == N) {
//		if (fin != 0) {
//			return 1_mi;
//		}
//		return 0_mi;
//	}
//
//	auto& memo = dp1[i][a_len][fin];
//	if (used1[i][a_len][fin]) {
//		return memo;
//	}
//	used1[i][a_len][fin] = true;
//
//	return memo = func1(i + 1, a_len + 1, fin) + func1(i + 1, 0, fin);
// }

mint pow2[5100];
mint dp5[5100][5100];
bool used5[5100][5100];
mint func4(int i, int a_max, int onB);
mint func5(int ic, int icend) {
  if (ic >= icend) {
    return 0_mi;
  }

  auto &memo = dp5[ic][icend];
  if (used5[ic][icend]) {
    return memo;
  }
  used5[ic][icend] = true;

  memo = func4(ic + 1, ic + A - 1, 0);
  memo += func5(ic + 1, icend);

  return memo;
}
mint dp4[5100][5100][2];
bool used4[5100][5100][2];
mint func4(int i, int a_max, int onB) {
  if (N <= a_max) {
    return 0_mi;
  }
  if (a_max < i) {
    return pow2[N - i];
  }
  if (i >= N) {
    return 0_mi;
  }

  auto &memo = dp4[i][a_max][onB];
  if (used4[i][a_max][onB]) {
    return memo;
  }
  used4[i][a_max][onB] = true;

  if (onB != 0) {
    return memo = func4(i + 1, a_max, 0) + func4(i + 1, a_max, 1);
  }

  memo = func4(i + 1, a_max, 0);
  // for (size_t c = 1; c < B; c++)
  //{
  //	memo += func4(i + c + 1, i + c + A-1, 0);
  // }
  memo += func5(i + 1, std::min(i + B, N));
  memo += func4(i + B, a_max, 1);
  return memo;
}

int main() {
  using std::endl;
  in.sync_with_stdio(false);
  out.sync_with_stdio(false);
  in.tie(nullptr);
  out.tie(nullptr);

  pow2[0] = 1;
  for (size_t i = 0; i < 5050; i++) {
    pow2[i + 1] = pow2[i] + pow2[i];
  }

  in >> N >> A >> B;
  if (A < B) {
    std::swap(A, B);
  }
  if (A == 1) {
    out << pow2[N] << endl;
    return 0;
  }

  // out <<
  //	func1(0, 0, 0) +
  //	func2(0, 0, 0) * (func3(A) - 1_mi) << endl;
  out << func4(0, A - 1, 0) << endl;

  return 0;
}
#endif


Error: -11

Fixed submission:


#if 1
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

auto &in = std::cin;
auto &out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const double PI =
    3.141592653589793238462643383279502884197169399375105820974944;

template <typename Arithmetic, typename Integral>
std::enable_if_t<std::is_unsigned<Integral>::value, Arithmetic>
ipow(Arithmetic bace, Integral n) {
  // 繰り返し二条法
  auto res = (Arithmetic)(1);
  while (n > 0) {
    if (n & 1)
      res *= bace;
    bace *= bace;
    n >>= 1;
  }
  return res;
}
constexpr bool is_prime(uint32_t N) {
  if (N <= 1) {
    return false;
  }
  for (size_t i = 2; i * i <= N; ++i) {
    if (N % i == 0) {
      return false;
    }
  }
  return true;
}
template <uint64_t MOD> class mint_base;
// mint_base_base型用の累乗関数
template <uint64_t MOD>
constexpr mint_base<MOD> m_pow(mint_base<MOD> x, uint64_t n) noexcept;
// mod計算を自動で行う整数テンプレートクラス
template <uint64_t MOD_ = 1000000007> class mint_base {
public:
  static constexpr auto MOD = MOD_;
  static_assert(!(MOD <= 2), "MOD cannot be below 2.");
  static_assert(MOD <= (0xFFFFFFFFFFFFFFFF / 2),
                "MOD is too big"); // 加算してオーバーフローしない
  static_assert(MOD <= 0xFFFFFFFF,
                "MOD is too big"); // 乗算してオーバーフローしない
  constexpr mint_base<MOD>
  operator+(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v += other;
  }
  constexpr mint_base<MOD>
  operator-(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v -= other;
  }
  constexpr mint_base<MOD>
  operator*(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v *= other;
  }
  constexpr auto operator/(const mint_base<MOD> &other) const noexcept {
    auto v = *this;
    return v /= other;
  }
  constexpr mint_base<MOD> &operator+=(const mint_base<MOD> &other) noexcept {
    a += other.a;
    if (MOD <= a) {
      a -= MOD;
    };
    return *this;
  }
  constexpr mint_base<MOD> &operator-=(const mint_base<MOD> &other) noexcept {
    if (a >= other.a) {
      a -= other.a;
    } else {
      a = (a + MOD) - other.a;
    }
    return *this;
  }
  constexpr mint_base<MOD> &operator*=(const mint_base<MOD> &other) noexcept {
#if 1
    a *= other.a;
    a %= MOD;
#else
    // MOD <= (MAXUINT64 / 2)条件下
    uint64_t b = other.a, v = 0;
    while (b > 0) {
      if (b & 1) {
        v += a;
        if (v >= MOD)
          v -= MOD;
      }
      a += a;
      if (MOD <= a)
        a -= MOD;
      b >>= 1;
    }
    a = v;
#endif
    return *this;
  }
  constexpr mint_base<MOD> &operator/=(const mint_base<MOD> &other) noexcept {
    return *this *= ~other;
  }
  constexpr mint_base<MOD> operator+() const noexcept { return *this; }
  constexpr mint_base<MOD> operator-() const noexcept {
    return {MOD - a, mod_value_tag{}};
  }
  constexpr mint_base<MOD> &operator++() noexcept {
    if (MOD <= ++a) {
      a = 0;
    };
    return *this;
  }
  constexpr mint_base<MOD> &operator--() noexcept {
    if (a <= 0) {
      a = MOD;
    };
    --a;
    return *this;
  }
  constexpr mint_base<MOD> operator++(int) noexcept {
    auto tmp = *this;
    ++*this;
    return tmp;
  }
  constexpr mint_base<MOD> operator--(int) noexcept {
    auto tmp = *this;
    --*this;
    return tmp;
  }
  constexpr mint_base<MOD> operator~() const noexcept {
    return ipow(*this, e_phi - 1);
  }
  constexpr mint_base<MOD> &operator=(const mint_base<MOD> &other) noexcept {
    a = other.a;
    return *this;
  }
  constexpr explicit operator uint64_t() 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:
  static constexpr uint64_t get_e_phi() noexcept {
    // オイラー値の導出
    uint64_t temp = MOD;
    uint64_t m_ = MOD;
    for (uint64_t i = 2; i * i <= m_; ++i) {
      if (m_ % i == 0) {
        temp = temp / i * (i - 1);
        for (; m_ % i == 0; m_ /= i)
          ;
      }
    }
    if (m_ != 1)
      temp = temp / m_ * (m_ - 1);
    return temp;
  }
  static constexpr uint64_t e_phi = get_e_phi(); // オイラー値
  uint64_t a;
};
// mint_base型用の累乗関数
template <uint64_t MOD>
constexpr mint_base<MOD> m_pow(mint_base<MOD> x, uint64_t n) noexcept {
  mint_base<MOD> res = 1;
  while (n > 0) {
    if (n & 1)
      res *= x;
    x *= x;
    n >>= 1;
  }
  return res;
}
// mint_baseの階乗計算
// O(x)時間が必要のため、fact_set関数を推奨する。
template <uint64_t MOD>
constexpr mint_base<MOD> fact(mint_base<MOD> x) noexcept {
  mint_base<MOD> res(1);
  for (uint64_t i = 1; i <= (uint64_t)x; ++i) {
    res *= i;
  }
  return res;
}
// mint_baseの階乗計算
// 0からxまでの階乗を返す
// O(x)時間が必要
template <uint64_t MOD>
std::vector<mint_base<MOD>> fact_set(mint_base<MOD> x = mint_base<MOD>(-1)) {
  mint_base<MOD> res(1);
  std::vector<mint_base<MOD>> set((uint64_t)(x) + 1);
  set[0] = 1;
  for (uint64_t i = 1; i <= (uint64_t)x; ++i) {
    res *= i;
    set[i] = res;
  }
  return res;
}
// mint_base型のstreamへの出力
template <uint64_t MOD>
std::ostream &operator<<(std::ostream &os, mint_base<MOD> i) {
  os << (uint64_t)i;
  return os;
}
// mint_base型のstreamからの入力
template <uint64_t MOD>
std::istream &operator>>(std::istream &is, mint_base<MOD> &i) {
  uint64_t tmp;
  is >> tmp;
  i = tmp;
  return is;
}
typedef mint_base<> mint;
namespace mint_literal {
constexpr mint operator""_mi(unsigned long long x) noexcept { return mint(x); }
} // namespace mint_literal
using namespace mint_literal;
// mint_baseの階乗計算
// 0からxまでの階乗を返す
// O(N)
template <int32_t X, uint64_t MOD = mint::MOD>
/*constexpr*/ std::array<mint_base<MOD>, X + 1> fact_set_c() {
  mint_base<MOD> res(1);
  std::array<mint_base<MOD>, X + 1> set;
  set[0] = 1;
  for (int32_t i = 1; i <= X; ++i) {
    res *= i;
    set[i] = res;
  }
  return set;
}

int32_t N, A, B;

mint pow2[5100];
mint dp5[5100][5100];
bool used5[5100][5100];
mint func4(int i, int a_max, int onB);
mint func5(int ic, int icend) {
  if (ic >= icend) {
    return 0_mi;
  }

  auto &memo = dp5[ic][icend];
  if (used5[ic][icend]) {
    return memo;
  }
  used5[ic][icend] = true;

  memo = func4(ic + 1, ic + A - 1, 0);
  memo += func5(ic + 1, icend);

  return memo;
}
mint dp4[5100][5100][2];
bool used4[5100][5100][2];
mint func4(int i, int a_max, int onB) {
  if (N <= a_max) {
    return 0_mi;
  }
  if (a_max < i) {
    return pow2[N - i];
  }
  if (i >= N) {
    return 0_mi;
  }

  auto &memo = dp4[i][a_max][onB];
  if (used4[i][a_max][onB]) {
    return memo;
  }
  used4[i][a_max][onB] = true;

  if (onB != 0) {
    return memo = func4(i + 1, a_max, 0) + func4(i + 1, a_max, 1);
  }

  memo = func4(i + 1, a_max, 0);
  // for (size_t c = 1; c < B; c++)
  //{
  //	memo += func4(i + c + 1, i + c + A-1, 0);
  // }
  memo += func5(i + 1, i + B);
  memo += func4(i + B, a_max, 1);
  return memo;
}

int main() {
  using std::endl;
  in.sync_with_stdio(false);
  out.sync_with_stdio(false);
  in.tie(nullptr);
  out.tie(nullptr);

  pow2[0] = 1;
  for (size_t i = 0; i < 5050; i++) {
    pow2[i + 1] = pow2[i] + pow2[i];
  }

  in >> N >> A >> B;
  if (A < B) {
    std::swap(A, B);
  }
  if (A == 1) {
    out << pow2[N] << endl;
    return 0;
  }

  // out <<
  //	func1(0, 0, 0) +
  //	func2(0, 0, 0) * (func3(A) - 1_mi) << endl;
  out << func4(0, A - 1, 0) << endl;

  return 0;
}
#endif