#include template T power(T a, Int n) { __glibcxx_assert(n >= 0); if (n == 0) return 1; for (; ~n & 1; n >>= 1) a *= a; T res = a; while (n >>= 1) { a *= a; if (n & 1) res *= a; } return res; } template class GetInverse; template class Fp { public: static_assert([](int n) -> bool { for (int i = 2; i * i <= n; ++i) if (n % i == 0) return false; return 3 <= n and n < 1 << 30; }(P)); static constexpr int mod() { return P; } Fp() : v(0) {} template Fp(const Int& a) : v(a % mod()) { v = (uint64_t(v + P) << 32) % P; } int val() const { int res = reduce(v) - P; return res < 0 ? res + P : res; } Fp& operator++() { return *this += 1; } Fp& operator--() { return *this -= 1; } Fp& operator*=(Fp o) { return v = reduce(uint64_t(v) * o.v), *this; } Fp& operator/=(Fp o) { return *this *= GetInverse{}(o); } Fp& operator+=(Fp o) { return v = int(v += o.v - 2 * P) < 0 ? v + 2 * P : v, *this; } Fp& operator-=(Fp o) { return v = int(v -= o.v) < 0 ? v + 2 * P : v, *this; } friend Fp operator++(Fp& a, int) { return std::exchange(a, ++Fp(a)); } friend Fp operator--(Fp& a, int) { return std::exchange(a, --Fp(a)); } friend Fp operator+(Fp a) { return a; } friend Fp operator-(Fp a) { return Fp{} -= a; } friend Fp operator*(Fp a, Fp b) { return a *= b; } friend Fp operator/(Fp a, Fp b) { return a /= b; } friend Fp operator+(Fp a, Fp b) { return a += b; } friend Fp operator-(Fp a, Fp b) { return a -= b; } friend bool operator==(Fp a, Fp b) { return a.v == b.v or a.v + P == b.v or a.v == b.v + P; } friend bool operator!=(Fp a, Fp b) { return not(a == b); } private: static constexpr uint32_t R = []() -> uint32_t { uint32_t res = -P; for (int _ = 4; _--;) res *= P * res + 2; return res; }(); static uint32_t reduce(uint64_t x) { return (x + P * uint64_t(R * uint32_t(x))) >> 32; } uint32_t v; }; template class GetInverse> { public: static void init(int n) { inv.reserve(n + 1); for (int i = std::size(inv); i <= n;) { int q = P / i, j = std::min(P / q, n); for (; i <= j; ++i) inv.push_back(-q * inv[P - q * i]); } } Fp

operator()(Fp

a) const { __glibcxx_assert(a.val()); if ((-a).val() < int(std::size(inv))) return -inv[(-a).val()]; int y0 = 0, z0 = P, y1 = 1, z1 = a.val(); while (z1 >= std::max(std::size(inv), 2)) std::swap(y0 -= z0 / z1 * y1, y1), std::swap(z0 %= z1, z1); return z1 > 1 ? y1 * inv[z1] : y1; } private: static inline std::vector> inv{0, 1}; }; namespace linear_sieve { std::vector primes, lpf; void init(int n) { if (n < int(std::size(lpf))) return; if (n < 2 * int(std::size(lpf))) n = 2 * std::size(lpf); lpf.resize(n + 1, -1); for (int d = 2; d <= n; ++d) { if (lpf[d] == -1) lpf[d] = d, primes.push_back(d); for (int p : primes) { if (p * d > n or p > lpf[d]) break; lpf[p * d] = p; } } } std::vector factor(int n) { __glibcxx_assert(n >= 1); std::vector res; for (init(n); n > 1; n /= res.back()) res.push_back(lpf[n]); return res; } } // namespace linear_sieve int main() { using namespace std; cin.tie(nullptr)->sync_with_stdio(false); int n; cin >> n; linear_sieve::init(n - 1); using Mint = Fp<998244353>; Mint ans = 1; for (int p : linear_sieve::primes) { int t = n, e = 0; while (t % p == 0) { t /= p; ++e; } int64_t cur = 1; int f = 0; while (cur * p <= t) { cur *= p; ++f; } ans *= power(p, 2 * e + f); } cout << ans.val() << '\n'; }