Problem p03253 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <iostream>
#include <limits.h>
#include <numeric>
#include <vector>

#define YesNo(b) ((b) ? "Yes" : "No")
#define YESNO(b) ((b) ? "YES" : "NO")

using namespace std;
using vi = vector<int>;
using vvi = vector<vi>;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
#include <iostream>
#include <numeric>
#include <vector>

constexpr uint_fast64_t MOD = 1e9 + 7;

template <class StoreT, class AddT, class MulT, StoreT MOD> class ModInt {
  using self_type = ModInt<StoreT, AddT, MulT, MOD>;
  StoreT i;

public:
  ModInt() : i(0) {}
  ModInt(StoreT i) {
    while (i < 0)
      i += MOD;
    this->i = i;
  }

  ModInt(const self_type &i) = default;
  constexpr self_type &operator=(const self_type &i) = default;

  constexpr uint_fast32_t getI() const noexcept { return i; }

  ModInt &operator+=(self_type rhs) {
    AddT i64 = static_cast<AddT>(i);
    StoreT a32 = static_cast<StoreT>((i64 + rhs.i) % MOD);
    i = a32;
    return *this;
  }

  constexpr ModInt operator+(self_type rhs) const noexcept {
    self_type newInt(*this);
    newInt += rhs;
    return newInt;
  }

  ModInt &operator-=(self_type rhs) {
    AddT i64 = static_cast<AddT>(i);
    StoreT a32 = static_cast<StoreT>((i64 + MOD - rhs.i) % MOD);
    i = a32;
    return *this;
  }

  constexpr ModInt operator-(self_type rhs) const noexcept {
    self_type newInt(*this);
    newInt -= rhs;
    return newInt;
  }

  ModInt &operator*=(self_type rhs) {
    MulT i64 = static_cast<MulT>(i);
    StoreT a32 = static_cast<StoreT>((i64 * rhs.i) % MOD);
    i = a32;
    return *this;
  }

  constexpr ModInt operator*(self_type rhs) const noexcept {
    self_type newInt(*this);
    newInt *= rhs;
    return newInt;
  }

  constexpr ModInt operator/(self_type rhs) const noexcept {
    self_type newInt(*this);
    self_type rhsInv = rhs.inv();
    newInt *= rhsInv;
    return newInt;
  }

  constexpr bool operator==(self_type rhs) const noexcept { return i == rhs.i; }

  constexpr bool operator<(self_type rhs) const noexcept { return i < rhs.i; }

  constexpr bool operator>(self_type rhs) const noexcept { return rhs < *this; }

  constexpr ModInt pow(int n) const noexcept {
    ModInt a = *this;
    ModInt res = 1;

    while (n > 0) {
      if (n & 1) {
        res *= a;
      }
      a *= a;
      n >>= 1;
    }
    return res;
  }

  constexpr self_type inv() const noexcept { return pow(MOD - 2); }
};

template <class StoreT, class AddT, class MulT, StoreT MOD>
std::ostream &operator<<(std::ostream &ost, ModInt<StoreT, AddT, MulT, MOD> i) {
  ost << i.getI();
  return ost;
}

using UModInt = ModInt<uint_fast32_t, uint_fast32_t, uint_fast64_t, MOD>;
using SModInt = ModInt<int_fast32_t, int_fast32_t, int_fast64_t, MOD>;

template <class ModIntT> class BinomialFactory {
  std::vector<ModIntT> stock;
  std::vector<ModIntT> inv;

public:
  explicit BinomialFactory(int N) {
    stock.resize(N + 1);
    inv.resize(N + 1);
    stock[0] = 1;
    inv[0] = 1;
    for (int i = 1; i <= N; i++) {
      stock[i] = stock[i - 1] * i;
      inv[i] = stock[i].inv();
    }
  }

  ModIntT bi(int n, int r) const {
    if (r == 0 || r == n)
      return 1;

    return stock[n] * inv[n - r] * inv[r];
  }
};

#include <cmath>
#include <unordered_map>
#include <vector>

using prime_map = std::unordered_map<int, int>;
class Factoriser {
  std::vector<int> factors;

public:
  Factoriser(int N) {
    factors.resize(N + 1, 0);
    int sqrN = static_cast<int>(std::sqrt(N));

    for (int i = 2; i <= sqrN; ++i) {
      if (factors[i] == 0) {
        for (int j = i * 2; j <= N; j += i) {
          if (factors[j] == 0) {
            factors[j] = i;
          }
        }
      }
    }
  }

  prime_map Factorise(int M) const {
    prime_map P;
    int mm = M;

    while (factors[mm]) {
      ++P[factors[mm]];
      mm /= factors[mm];
    }

    if (mm >= 2)
      ++P[mm];
    return P;
  }

  static prime_map DirectFactorise(int M) {
    prime_map P;

    int i = 2;
    while (M > 0) {
      if (M % i == 0) {
        ++P[i];
        M /= i;
      } else {
        ++i;
      }
    }
    return P;
  }

  bool IsPrime(int M) const { return factors[M] == 0; }
};

int main() {
  int N, M;
  cin >> N >> M;

  BinomialFactory<UModInt> bifac(N + 100000);
  prime_map pm = Factoriser::DirectFactorise(M);

  UModInt ans = 1;
  for (auto t : pm)
    ans *= bifac.bi(t.second + N - 1, N - 1);

  cout << ans << endl;
}


Fixed submission:
#include <algorithm>
#include <cmath>
#include <iostream>
#include <limits.h>
#include <numeric>
#include <vector>

#define YesNo(b) ((b) ? "Yes" : "No")
#define YESNO(b) ((b) ? "YES" : "NO")

using namespace std;
using vi = vector<int>;
using vvi = vector<vi>;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
#include <iostream>
#include <numeric>
#include <vector>

constexpr uint_fast64_t MOD = 1e9 + 7;

template <class StoreT, class AddT, class MulT, StoreT MOD> class ModInt {
  using self_type = ModInt<StoreT, AddT, MulT, MOD>;
  StoreT i;

public:
  ModInt() : i(0) {}
  ModInt(StoreT i) {
    while (i < 0)
      i += MOD;
    this->i = i;
  }

  ModInt(const self_type &i) = default;
  constexpr self_type &operator=(const self_type &i) = default;

  constexpr uint_fast32_t getI() const noexcept { return i; }

  ModInt &operator+=(self_type rhs) {
    AddT i64 = static_cast<AddT>(i);
    StoreT a32 = static_cast<StoreT>((i64 + rhs.i) % MOD);
    i = a32;
    return *this;
  }

  constexpr ModInt operator+(self_type rhs) const noexcept {
    self_type newInt(*this);
    newInt += rhs;
    return newInt;
  }

  ModInt &operator-=(self_type rhs) {
    AddT i64 = static_cast<AddT>(i);
    StoreT a32 = static_cast<StoreT>((i64 + MOD - rhs.i) % MOD);
    i = a32;
    return *this;
  }

  constexpr ModInt operator-(self_type rhs) const noexcept {
    self_type newInt(*this);
    newInt -= rhs;
    return newInt;
  }

  ModInt &operator*=(self_type rhs) {
    MulT i64 = static_cast<MulT>(i);
    StoreT a32 = static_cast<StoreT>((i64 * rhs.i) % MOD);
    i = a32;
    return *this;
  }

  constexpr ModInt operator*(self_type rhs) const noexcept {
    self_type newInt(*this);
    newInt *= rhs;
    return newInt;
  }

  constexpr ModInt operator/(self_type rhs) const noexcept {
    self_type newInt(*this);
    self_type rhsInv = rhs.inv();
    newInt *= rhsInv;
    return newInt;
  }

  constexpr bool operator==(self_type rhs) const noexcept { return i == rhs.i; }

  constexpr bool operator<(self_type rhs) const noexcept { return i < rhs.i; }

  constexpr bool operator>(self_type rhs) const noexcept { return rhs < *this; }

  constexpr ModInt pow(int n) const noexcept {
    ModInt a = *this;
    ModInt res = 1;

    while (n > 0) {
      if (n & 1) {
        res *= a;
      }
      a *= a;
      n >>= 1;
    }
    return res;
  }

  constexpr self_type inv() const noexcept { return pow(MOD - 2); }
};

template <class StoreT, class AddT, class MulT, StoreT MOD>
std::ostream &operator<<(std::ostream &ost, ModInt<StoreT, AddT, MulT, MOD> i) {
  ost << i.getI();
  return ost;
}

using UModInt = ModInt<uint_fast32_t, uint_fast32_t, uint_fast64_t, MOD>;
using SModInt = ModInt<int_fast32_t, int_fast32_t, int_fast64_t, MOD>;

template <class ModIntT> class BinomialFactory {
  std::vector<ModIntT> stock;
  std::vector<ModIntT> inv;

public:
  explicit BinomialFactory(int N) {
    stock.resize(N + 1);
    inv.resize(N + 1);
    stock[0] = 1;
    inv[0] = 1;
    for (int i = 1; i <= N; i++) {
      stock[i] = stock[i - 1] * i;
      inv[i] = stock[i].inv();
    }
  }

  ModIntT bi(int n, int r) const {
    if (r == 0 || r == n)
      return 1;

    return stock[n] * inv[n - r] * inv[r];
  }
};

#include <cmath>
#include <unordered_map>
#include <vector>

using prime_map = std::unordered_map<int, int>;
class Factoriser {
  std::vector<int> factors;

public:
  Factoriser(int N) {
    factors.resize(N + 1, 0);
    int sqrN = static_cast<int>(std::sqrt(N));

    for (int i = 2; i <= sqrN; ++i) {
      if (factors[i] == 0) {
        for (int j = i * 2; j <= N; j += i) {
          if (factors[j] == 0) {
            factors[j] = i;
          }
        }
      }
    }
  }

  prime_map Factorise(int M) const {
    prime_map P;
    int mm = M;

    while (factors[mm]) {
      ++P[factors[mm]];
      mm /= factors[mm];
    }

    if (mm >= 2)
      ++P[mm];
    return P;
  }

  static prime_map DirectFactorise(int M) {
    prime_map P;

    int i = 2;
    while (M > 1) {
      if (M % i == 0) {
        ++P[i];
        M /= i;
      } else {
        ++i;
      }
    }
    return P;
  }

  bool IsPrime(int M) const { return factors[M] == 0; }
};

int main() {
  int N, M;
  cin >> N >> M;

  BinomialFactory<UModInt> bifac(N + 100000);
  prime_map pm = Factoriser::DirectFactorise(M);

  UModInt ans = 1;
  for (auto t : pm)
    ans *= bifac.bi(t.second + N - 1, N - 1);

  cout << ans << endl;
}