Problem p03748 (C++)

Buggy submission (status: Runtime Error):

#if 1
#include <algorithm>
#include <array>
#include <assert.h>
#include <cstdint>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#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;
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 std::enable_if_t<is_prime(MOD), mint_base<MOD> &>
  operator/=(const mint_base<MOD> &other) noexcept {
    return *this *= ipow(other, MOD - 2);
  }
  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<1000000007> 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) //O(1)
template <uint64_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 (uint64_t i = 1; i <= X; ++i) {
    res *= i;
    set[i] = res;
  }
  return set;
}
int32_t N;
bool used[3000][3001][2];
mint dp[3000][3001][2]; // M,R
mint func(int m, int r, int has_full) {
  if (m == 0) {
    return (has_full == 1) ? 1_mi : 0_mi;
  }
  if (has_full == 0) {
    if (r == 0 || r == N) {
      has_full = 1;
    }
  }
  if (used[m][r][has_full]) {
    return dp[m][r][has_full];
  }
  used[m][r][has_full] = true;
  auto &memo = dp[m][r][has_full];
  memo = 0;
  if (r > 0) {
    // rr
    memo += func(m - 1, r - 1, has_full);
    // rb
    memo += func(m - 1, r, has_full);
  }
  if (r < N) {
    // br
    memo += func(m - 1, r, has_full);
    // bb
    memo += func(m - 1, r + 1, has_full);
  }
  return memo;
}
int main() {
  using std::endl;
  in.sync_with_stdio(false);
  out.sync_with_stdio(false);
  int32_t m;
  in >> N >> m;
  mint res;
  // res += func(m, N/2,1);
  for (int32_t i = 0; i <= N; ++i) {
    // if(i!=N/2)
    res += func(m, i, 0);
  }
  out << res << endl;

  return 0;
}
#endif

Fixed submission:

#if 1
#include <algorithm>
#include <array>
#include <assert.h>
#include <cstdint>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#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;
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 std::enable_if_t<is_prime(MOD), mint_base<MOD> &>
  operator/=(const mint_base<MOD> &other) noexcept {
    return *this *= ipow(other, MOD - 2);
  }
  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<1000000007> 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) //O(1)
template <uint64_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 (uint64_t i = 1; i <= X; ++i) {
    res *= i;
    set[i] = res;
  }
  return set;
}
int32_t N;
bool used[3001][3001][2];
mint dp[3001][3001][2]; // M,R
mint func(int m, int r, int has_full) {
  if (m == 0) {
    return (has_full == 1) ? 1_mi : 0_mi;
  }
  if (has_full == 0) {
    if (r == 0 || r == N) {
      has_full = 1;
    }
  }
  if (used[m][r][has_full]) {
    return dp[m][r][has_full];
  }
  used[m][r][has_full] = true;
  auto &memo = dp[m][r][has_full];
  memo = 0;
  if (r > 0) {
    // rr
    memo += func(m - 1, r - 1, has_full);
    // rb
    memo += func(m - 1, r, has_full);
  }
  if (r < N) {
    // br
    memo += func(m - 1, r, has_full);
    // bb
    memo += func(m - 1, r + 1, has_full);
  }
  return memo;
}
int main() {
  using std::endl;
  in.sync_with_stdio(false);
  out.sync_with_stdio(false);
  int32_t m;
  in >> N >> m;
  mint res;
  // res += func(m, N/2,1);
  for (int32_t i = 0; i <= N; ++i) {
    // if(i!=N/2)
    res += func(m, i, 0);
  }
  out << res << endl;

  return 0;
}
#endif