結果
問題 | No.502 階乗を計算するだけ |
ユーザー | Tifa |
提出日時 | 2023-10-20 03:36:15 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 153 ms / 1,000 ms |
コード長 | 19,236 bytes |
コンパイル時間 | 2,624 ms |
コンパイル使用メモリ | 231,840 KB |
実行使用メモリ | 10,124 KB |
最終ジャッジ日時 | 2024-09-19 23:21:39 |
合計ジャッジ時間 | 5,404 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 1 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 1 ms
5,376 KB |
testcase_04 | AC | 1 ms
5,376 KB |
testcase_05 | AC | 1 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 1 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 1 ms
5,376 KB |
testcase_13 | AC | 1 ms
5,376 KB |
testcase_14 | AC | 1 ms
5,376 KB |
testcase_15 | AC | 2 ms
5,376 KB |
testcase_16 | AC | 1 ms
5,376 KB |
testcase_17 | AC | 2 ms
5,376 KB |
testcase_18 | AC | 2 ms
5,376 KB |
testcase_19 | AC | 2 ms
5,376 KB |
testcase_20 | AC | 1 ms
5,376 KB |
testcase_21 | AC | 2 ms
5,376 KB |
testcase_22 | AC | 6 ms
5,376 KB |
testcase_23 | AC | 4 ms
5,376 KB |
testcase_24 | AC | 5 ms
5,376 KB |
testcase_25 | AC | 4 ms
5,376 KB |
testcase_26 | AC | 5 ms
5,376 KB |
testcase_27 | AC | 3 ms
5,376 KB |
testcase_28 | AC | 5 ms
5,376 KB |
testcase_29 | AC | 3 ms
5,376 KB |
testcase_30 | AC | 5 ms
5,376 KB |
testcase_31 | AC | 6 ms
5,376 KB |
testcase_32 | AC | 144 ms
9,868 KB |
testcase_33 | AC | 146 ms
9,996 KB |
testcase_34 | AC | 144 ms
9,868 KB |
testcase_35 | AC | 71 ms
6,700 KB |
testcase_36 | AC | 153 ms
10,124 KB |
testcase_37 | AC | 142 ms
9,996 KB |
testcase_38 | AC | 144 ms
10,124 KB |
testcase_39 | AC | 145 ms
9,992 KB |
testcase_40 | AC | 70 ms
6,944 KB |
testcase_41 | AC | 144 ms
9,864 KB |
testcase_42 | AC | 2 ms
6,944 KB |
testcase_43 | AC | 2 ms
6,940 KB |
testcase_44 | AC | 2 ms
6,944 KB |
testcase_45 | AC | 1 ms
6,944 KB |
testcase_46 | AC | 2 ms
6,944 KB |
testcase_47 | AC | 2 ms
6,940 KB |
testcase_48 | AC | 1 ms
6,940 KB |
testcase_49 | AC | 1 ms
6,944 KB |
testcase_50 | AC | 2 ms
6,944 KB |
testcase_51 | AC | 2 ms
6,944 KB |
ソースコード
#line 1 "src/test_cpverifier/yukicoder/0502.fact_mint.pdd.0.test.cpp" #define PROBLEM "https://yukicoder.me/problems/no/502" #line 1 "src/code/math/fact_mint.hpp" #line 1 "src/code/poly/poly_ctsh.hpp" #line 1 "src/code/comb/ifact_mod_gen.hpp" #line 1 "src/code/comb/inv_mod_gen.hpp" #line 1 "src/code/math/mul_mod_u.hpp" #line 1 "src/code/bit/bwidth.hpp" #line 1 "src/code/bit/cntl0.hpp" namespace tifa_libs::bit { // From GCC lib template <typename T> constexpr int cntl0(T x) { constexpr int nd = sizeof(T) * 8; if (x == 0) return nd; static_assert(nd <= 128); constexpr int nd_ull = sizeof(unsigned long long) * 8; constexpr int nd_ul = sizeof(unsigned long) * 8; constexpr int nd_u = sizeof(unsigned) * 8; if constexpr (nd <= nd_u) return __builtin_clz(x) - (nd_u - nd); else if constexpr (nd <= nd_ul) return __builtin_clzl(x) - (nd_ul - nd); else if constexpr (nd <= nd_ull) return __builtin_clzll(x) - (nd_ull - nd); else { unsigned long long hi = x >> nd_ull; if (hi != 0) return __builtin_clzll(hi) - ((2 * nd_ull) - nd); unsigned long long lo = x & (unsigned long long)(-1); return (nd - nd_ull) + __builtin_clzll(lo); } } } // namespace tifa_libs::bit #line 5 "src/code/bit/bwidth.hpp" namespace tifa_libs::bit { // From GCC lib template <typename T> constexpr int bwidth(T x) { return (int)sizeof(T) * 8 - cntl0(x); } } // namespace tifa_libs::bit #line 1 "src/code/util/util.hpp" #include <bits/stdc++.h> namespace tifa_libs { using i8 = int8_t; using u8 = uint8_t; using i16 = int16_t; using u16 = uint16_t; using i32 = int32_t; using u32 = uint32_t; using i64 = int64_t; using u64 = uint64_t; using i128 = __int128_t; using u128 = __uint128_t; using isz = ptrdiff_t; using usz = size_t; template <class T> using vec = std::vector<T>; template <class T> using vvec = vec<vec<T>>; template <class T> using vvvec = vec<vvec<T>>; template <class T> using pq = std::priority_queue<T>; template <class T> using pqg = std::priority_queue<T, vec<T>, std::greater<T>>; template <class U, class T> using vvp = vvec<std::pair<U, T>>; template <class T> using ptt = std::pair<T, T>; template <class T> using pt3 = std::tuple<T, T, T>; template <class T> using pt4 = std::tuple<T, T, T, T>; #ifdef ONLINE_JUDGE #undef assert #define assert(x) 42 #endif } // namespace tifa_libs #line 6 "src/code/math/mul_mod_u.hpp" namespace tifa_libs::math { constexpr u64 mul_mod_u(u64 a, u64 b, u64 mod) { if (bit::bwidth(a) + bit::bwidth(b) <= 64) return a * b % mod; else return (u64)((u128)a * b % mod); } } // namespace tifa_libs::math #line 5 "src/code/comb/inv_mod_gen.hpp" namespace tifa_libs::math { // i^{-1} inline vec<u64> inv_mod_gen(size_t sz, u64 mod) { vec<u64> ans(sz, 1); for (size_t i = 2; i < sz; ++i) ans[i] = mul_mod_u(mod - mod / i, ans[mod % i], mod); return ans; } } // namespace tifa_libs::math #line 5 "src/code/comb/ifact_mod_gen.hpp" namespace tifa_libs::math { // (i!)^{-1} inline vec<u64> ifact_mod_gen(size_t sz, u64 mod, vec<u64> const& inv) { vec<u64> ans = inv; for (size_t i = 2; i < sz; ++i) ans[i] = mul_mod_u(ans[i], ans[i - 1], mod); return ans; } // (i!)^{-1} inline vec<u64> ifact_mod_gen(size_t sz, u64 mod) { return ifact_mod_gen(sz, mod, inv_mod_gen(sz, mod)); } } // namespace tifa_libs::math #line 1 "src/code/poly/poly.hpp" #line 5 "src/code/poly/poly.hpp" namespace tifa_libs::math { template <class Pldt> class poly { Pldt p; public: using value_type = typename Pldt::value_type; using data_type = vec<value_type>; explicit constexpr poly(size_t sz = 1) : p(sz) {} explicit constexpr poly(std::initializer_list<value_type> v) : p(v) {} template <class T> explicit constexpr poly(vec<T> const &v) : p(v) {} constexpr friend std::istream &operator>>(std::istream &is, poly &poly) { for (auto &val : poly.p.d) is >> val; return is; } constexpr friend std::ostream &operator<<(std::ostream &os, const poly &poly) { if (!poly.size()) return os; for (size_t i = 1; i < poly.size(); ++i) os << poly[i - 1] << ' '; return os << poly.p.d.back(); } constexpr size_t size() const { return p.d.size(); } constexpr data_type &data() { return p.d; } constexpr data_type const &data() const { return p.d; } constexpr value_type &operator[](size_t x) { return p.d[x]; } constexpr value_type operator[](size_t x) const { return p.d[x]; } constexpr value_type operator()(value_type x) const { value_type ans = 0; for (size_t i = size() - 1; ~i; --i) ans = ans * x + p.d[i]; return ans; } template <class F> void apply_range(size_t l, size_t r, F f) { assert(l < r && r <= size()); for (size_t i = l; i < r; ++i) f(i, p.d[i]); } template <class F> void apply(F f) { apply_range(0, size(), f); } constexpr void resize(size_t size) { p.d.resize(size); } constexpr poly pre(size_t size) const { poly _ = *this; _.resize(size); return _; } constexpr void strip() { auto it = std::find_if(p.d.rbegin(), p.d.rend(), [](auto const &x) { return x != 0; }); p.d.resize(p.d.rend() - it); if (p.d.empty()) p.d.push_back(value_type(0)); } constexpr void reverse(size_t n = 0) { std::reverse(p.d.begin(), p.d.begin() + (n ? n : size())); } void conv(poly const &r, size_t ans_size) { p.conv(r.p, ans_size); } void conv(poly const &r) { p.conv(r.p); } constexpr poly operator-() const { poly ret = *this; ret.apply([]([[maybe_unused]] size_t i, auto &v) { v = -v; }); return ret; } friend poly operator+(poly p, value_type c) { p[0] += c; return p; } friend poly operator+(value_type c, poly const &p) { return p + c; } friend poly operator-(poly p, value_type c) { p[0] -= c; return p; } friend poly operator-(value_type c, poly const &p) { return p - c; } constexpr poly &operator*=(value_type c) { apply([&c]([[maybe_unused]] size_t i, auto &v) { v *= c; }); return *this; } constexpr friend poly operator*(poly p, value_type c) { return p *= c; } constexpr friend poly operator*(value_type c, poly p) { return p *= c; } constexpr poly &operator+=(poly const &r) { if (!r.size()) return *this; resize(std::max(size(), r.size())); apply_range(0, r.size(), [&r](size_t i, auto &v) { v += r[i]; }); return *this; } friend poly operator+(poly l, poly const &r) { return l += r; } constexpr poly &operator-=(poly const &r) { if (!r.size()) return *this; resize(std::max(size(), r.size())); apply_range(0, r.size(), [&r](size_t i, auto &v) { v -= r[i]; }); return *this; } friend poly operator-(poly l, poly const &r) { return l -= r; } poly &operator*=(poly const &r) { if (!r.size()) { resize(1); p.d[0] = 0; return *this; } conv(r); return *this; } friend poly operator*(poly l, poly const &r) { return l *= r; } }; } // namespace tifa_libs::math #line 6 "src/code/poly/poly_ctsh.hpp" namespace tifa_libs::math { template <class T> inline poly<T> poly_ctsh(poly<T> const &f, typename T::value_type c, vec<u64> const &ifact, usz m = 0) { usz n = f.size(), k = f.size() - 1; if (!m) m = n; using mint = typename T::value_type; u64 t = c.val(); if (t <= k) { poly<T> ret(m); usz ptr = 0; for (usz i = t; i <= k && ptr < m; ++i) ret[ptr++] = f[i]; if (k + 1 < t + m) { auto suf = poly_ctsh(f, k + 1, ifact, m - ptr); for (usz i = k + 1; i < t + m; ++i) ret[ptr++] = suf[i - (k + 1)]; } return ret; } if (t + m > mint::mod()) { auto pref = poly_ctsh(f, t, ifact, mint::mod() - t), suf = poly_ctsh(f, 0, ifact, m - pref.size()); std::copy(suf.data().begin(), suf.data().end(), std::back_inserter(pref.data())); return pref; } poly<T> d(k + 1); for (usz i = 0; i <= k; ++i) { d[i] = ifact[i]; (d[i] *= ifact[k - i]) *= f[i]; if ((k - i) & 1) d[i] = -d[i]; } poly<T> h(m + k); for (usz i = 0; i < m + k; ++i) h[i] = mint(t - k + i).inv(); auto dh = d * h; poly<T> ret(m); mint cur = t; for (usz i = 1; i <= k; ++i) cur *= t - i; for (usz i = 0; i < m; ++i) { ret[i] = cur * dh[k + i]; (cur *= t + i + 1) *= h[i]; } return ret; } template <class T> inline poly<T> poly_ctsh(poly<T> const &f, typename T::value_type c, usz m = 0) { usz n = f.size(); return poly_ctsh(f, c, ifact_mod_gen(n, T::value_type::mod()), m); } } // namespace tifa_libs::math #line 5 "src/code/math/fact_mint.hpp" namespace tifa_libs::math { template <class polydata, class mint = typename polydata::value_type> inline mint fact_mint(u64 n) { if (n <= 1) return 1; if (n >= mint::mod()) return 0; using poly_t = poly<polydata>; u64 v = 1; while (v * v < n) v *= 2; mint iv = mint(v).inv(); poly_t g{1, v + 1}; for (u64 d = 1; d != v; d *= 2) { poly_t g1 = poly_ctsh(g, mint(d) * iv), g2 = poly_ctsh(g, mint(d * v + v) * iv), g3 = poly_ctsh(g, mint(d * v + d + v) * iv); for (u64 i = 0; i <= d; ++i) g[i] *= g1[i], g2[i] *= g3[i]; std::copy(g2.data().begin(), g2.data().end() - 1, std::back_inserter(g.data())); } mint res = 1; u64 i = 0; while (i + v <= n) res *= g[i / v], i += v; while (i < n) res *= ++i; return res; } } // namespace tifa_libs::math #line 1 "src/code/math/mint_d31.hpp" #line 5 "src/code/math/mint_d31.hpp" namespace tifa_libs::math { template <int> class mint_d31 { u32 v_{}; static inline u32 norm(i32 x) { return (u32)(x + (-(x < 0) & (i32)MOD)); } static inline u32 redc(u64 x) { u32 t = (u32)((x + (u64)((u32)(x)*R) * MOD_ODD) >> 32); return t - (MOD_ODD & -((MOD_ODD - 1 - t) >> 31)); } static inline u32 tsf(u32 x) { return redc((u64)(x % MOD_ODD) * R2) << OFFSET | (x & MASK); } static inline u32 R, R2, MOD, MOD_ODD, OFFSET, MASK; static inline i32 SMOD; public: static inline void set_mod(u32 m) { assert(!(m == 1 || m >> 31)); for (MOD = MOD_ODD = m, OFFSET = 0; (MOD_ODD & 1) == 0; ++OFFSET, MOD_ODD >>= 1) ; MASK = (1 << OFFSET) - 1, SMOD = (i32)(MOD); { u32 t = 2, iv = MOD_ODD * (t - MOD_ODD * MOD_ODD); iv *= t - MOD_ODD * iv, iv *= t - MOD_ODD * iv; R = iv * (MOD_ODD * iv - t); } R2 = (u32)(-(u64)(MOD_ODD) % MOD_ODD); } static inline u32 mod() { return MOD; } static inline i32 smod() { return SMOD; } mint_d31() {} template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0> mint_d31(T v) : v_(tsf(norm((i32)(v % (T)SMOD)))) {} u32 val() const { u32 h = redc(v_ >> OFFSET); return ((h - v_) * R & MASK) * MOD_ODD + h; } i32 sval() const { return (i32)val(); } bool is_zero() const { return v_ == 0; } template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0> explicit operator T() const { return (T)(val()); } mint_d31 operator-() const { mint_d31 res; u32 h = v_ >> OFFSET; res.v_ = (((MOD_ODD & -(h != 0)) - h) << OFFSET) | (-v_ & MASK); return res; } mint_d31 inv() const { i32 x1 = 1, x3 = 0, a = sval(), b = SMOD; while (b != 0) { i32 q = a / b, x1_old = x1, a_old = a; x1 = x3, x3 = x1_old - x3 * q, a = b, b = a_old - b * q; } return mint_d31(x1); } mint_d31 &operator+=(const mint_d31 &rhs) { u32 h = (v_ >> OFFSET) + (rhs.v_ >> OFFSET) - MOD_ODD; v_ = ((h + (MOD_ODD & -(h >> 31))) << OFFSET) | ((v_ + rhs.v_) & MASK); return *this; } mint_d31 &operator-=(const mint_d31 &rhs) { u32 h = (v_ >> OFFSET) - (rhs.v_ >> OFFSET); v_ = ((h + (MOD_ODD & -(h >> 31))) << OFFSET) | ((v_ - rhs.v_) & MASK); return *this; } mint_d31 &operator*=(const mint_d31 &rhs) { v_ = (redc((u64)(v_ >> OFFSET) * (rhs.v_ >> OFFSET)) << OFFSET) | ((v_ * rhs.v_) & MASK); return *this; } mint_d31 &operator/=(const mint_d31 &rhs) { return operator*=(rhs.inv()); } mint_d31 pow(u64 e) const { for (mint_d31 res(1), x(*this);; x *= x) { if (e & 1) res *= x; if ((e >>= 1) == 0) return res; } } void swap(mint_d31 &rhs) { auto v = v_; v_ = rhs.v_, rhs.v_ = v; } friend mint_d31 operator+(const mint_d31 &lhs, const mint_d31 &rhs) { return mint_d31(lhs) += rhs; } friend mint_d31 operator-(const mint_d31 &lhs, const mint_d31 &rhs) { return mint_d31(lhs) -= rhs; } friend mint_d31 operator*(const mint_d31 &lhs, const mint_d31 &rhs) { return mint_d31(lhs) *= rhs; } friend mint_d31 operator/(const mint_d31 &lhs, const mint_d31 &rhs) { return mint_d31(lhs) /= rhs; } friend bool operator==(const mint_d31 &lhs, const mint_d31 &rhs) { return lhs.v_ == rhs.v_; } friend bool operator!=(const mint_d31 &lhs, const mint_d31 &rhs) { return lhs.v_ != rhs.v_; } friend constexpr bool operator<(const mint_d31 &lhs, const mint_d31 &rhs) { return lhs.val() < rhs.val(); } friend std::istream &operator>>(std::istream &is, mint_d31 &rhs) { i32 x; is >> x; rhs = mint_d31(x); return is; } friend std::ostream &operator<<(std::ostream &os, const mint_d31 &rhs) { return os << rhs.val(); } friend constexpr u32 abs(mint_d31 const &x) { return x.val(); } }; } // namespace tifa_libs::math #line 1 "src/code/poly/polydata_d.hpp" #line 1 "src/code/conv/conv_mtt.hpp" #line 1 "src/code/conv/fft.hpp" #line 1 "src/code/bit/bceil.hpp" #line 6 "src/code/bit/bceil.hpp" namespace tifa_libs::bit { // From GCC lib template <typename T> constexpr T bceil(T x) { if (x == 0 || x == 1) return 1; constexpr int nd = sizeof(T) * 8; int sh = nd - cntl0((T)(x - 1u)); using U = decltype(x << 1); if constexpr (!std::is_same_v<U, T>) sh |= (sh & nd) << (sizeof(U) / sizeof(T) / 2); return (T)1u << sh; } } // namespace tifa_libs::bit #line 1 "src/code/bit/log2.hpp" #line 5 "src/code/bit/log2.hpp" namespace tifa_libs::bit { template <typename T> constexpr int log2(T x) { return bwidth(x) - 1; } } // namespace tifa_libs::bit #line 6 "src/code/conv/fft.hpp" namespace tifa_libs::math { template <class FP> struct FFT { static_assert(std::is_floating_point_v<FP>); using C = std::complex<FP>; constexpr FFT() : rev(), w() {} size_t size() const { return rev.size(); } void bzr(size_t len) { size_t n = bit::bceil(len); int k = bit::log2(n); if (n == size()) return; rev.resize(n, 0); for (size_t i = 0; i < n; ++i) rev[i] = (rev[i / 2] / 2) | ((i & 1) << (k - 1)); w.resize(n); w[0].real(1); for (size_t i = 1; i < n; ++i) w[i] = {std::cos(TAU * (FP)i / (FP)n), std::sin(TAU * (FP)i / (FP)n)}; } void dif(vec<C> &f) const { size_t n = size(); assert(f.size() <= n); f.resize(n); for (size_t i = 0; i < n; ++i) if (i < rev[i]) std::swap(f[rev[i]], f[i]); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" for (size_t i = 2, d = n / 2; i <= n; i *= 2, d /= 2) for (size_t j = 0; j < n; j += i) { auto l = f.begin() + j, r = f.begin() + j + i / 2; auto p = w.begin(); for (size_t k = 0; k < i / 2; ++k, ++l, ++r, p += d) { C tmp = *r * *p; *r = *l - tmp; *l = *l + tmp; } } #pragma GCC diagnostic pop } void dit(vec<C> &f) const { size_t n = size(); dif(f); for (size_t i = 0; i < n; ++i) f[i] /= (FP)n; } private: const FP TAU = std::acos((FP)-1.) * 2; vec<size_t> rev; vec<C> w; }; } // namespace tifa_libs::math #line 6 "src/code/conv/conv_mtt.hpp" namespace tifa_libs::math { template <class mint, class FP = double> inline vec<mint> conv_mtt(vec<mint> const &l, vec<mint> const &r, size_t ans_size) { using C = typename FFT<FP>::C; static FFT<FP> fft; if (l.size() == 1) { vec<mint> ans = r; ans.resize(ans_size); for (auto &i : ans) i *= l[0]; return ans; } if (r.size() == 1) { vec<mint> ans = l; ans.resize(ans_size); for (auto &i : ans) i *= r[0]; return ans; } fft.bzr(std::min(l.size() + r.size() - 1, ans_size)); size_t n = fft.size(); const int OFS = ((int)sizeof(decltype(mint::mod())) * 8 - bit::cntl0(mint::mod() - 1) + 1) / 2; const u32 MSK = ((1u << OFS) - 1); vec<mint> ans(ans_size); vec<C> a(n), b(n); for (size_t i = 0; i < l.size(); ++i) a[i] = {(FP)(l[i].val() & MSK), (FP)(l[i].val() >> OFS)}; for (size_t i = 0; i < r.size(); ++i) b[i] = {(FP)(r[i].val() & MSK), (FP)(r[i].val() >> OFS)}; fft.dif(a); fft.dif(b); { vec<C> p(n), q(n); for (size_t i = 0, j; i < n; ++i) { j = (n - i) & (n - 1); C da = (a[i] + std::conj(a[j])) * C(.5, 0), db = (a[i] - std::conj(a[j])) * C(0, -.5), dc = (b[i] + std::conj(b[j])) * C(.5, 0), dd = (b[i] - std::conj(b[j])) * C(.5, 0); p[j] = da * dc + da * dd; q[j] = db * dc + db * dd; } a = p; b = q; } fft.dif(a); fft.dif(b); for (size_t i = 0; i < ans_size; ++i) { i64 da = (i64)(a[i].real() / (FP)n + .5) % mint::mod(), db = (i64)(a[i].imag() / (FP)n + .5) % mint::mod(), dc = (i64)(b[i].real() / (FP)n + .5) % mint::mod(), dd = (i64)(b[i].imag() / (FP)n + .5) % mint::mod(); ans[i] = da + ((db + dc) << OFS) % mint::mod() + (dd << (OFS * 2)) % mint::mod(); } return ans; } template <class mint, class FP = double> inline vec<mint> conv_mtt(vec<mint> const &l, vec<mint> const &r) { return conv_mtt<mint, FP>(l, r, l.size() + r.size() - 1); } } // namespace tifa_libs::math #line 1 "src/code/conv/conv_naive.hpp" #line 5 "src/code/conv/conv_naive.hpp" namespace tifa_libs::math { template <class U, class T = U> inline vec<T> conv_naive(vec<U> const &l, vec<U> const &r, size_t ans_size) { static_assert(sizeof(U) <= sizeof(T)); size_t n = l.size(), m = r.size(); vec<T> ans(ans_size); if (n < m) for (size_t j = 0; j < m; ++j) for (size_t i = 0; i < n; ++i) { if (i + j >= ans_size) break; ans[i + j] += (T)l[i] * (T)r[j]; } else for (size_t i = 0; i < n; ++i) for (size_t j = 0; j < m; ++j) { if (i + j >= ans_size) break; ans[i + j] += (T)l[i] * (T)r[j]; } return ans; } template <class U, class T = U> inline vec<T> conv_naive(vec<U> const &l, vec<U> const &r) { return conv_naive<U, T>(l, r, l.size() + r.size() - 1); } } // namespace tifa_libs::math #line 7 "src/code/poly/polydata_d.hpp" namespace tifa_libs::math { template <class mint> struct polydata_d { using value_type = mint; vec<mint> d; explicit constexpr polydata_d(size_t sz = 1) : d(sz) {} explicit constexpr polydata_d(std::initializer_list<mint> v) : d(v) {} explicit constexpr polydata_d(vec<mint> const &v) : d(v) {} void conv(polydata_d const &r, size_t ans_size) { d = ans_size < 32 ? conv_naive(d, r.d, ans_size) : conv_mtt(d, r.d, ans_size); } void conv(polydata_d const &r) { conv(r, d.size() + r.d.size() - 1); } }; } // namespace tifa_libs::math #line 6 "src/test_cpverifier/yukicoder/0502.fact_mint.pdd.0.test.cpp" constexpr tifa_libs::u64 MOD = 1000000007; using mint = tifa_libs::math::mint_d31<-1>; using pldt_t = tifa_libs::math::polydata_d<mint>; int main() { mint::set_mod(MOD); std::ios::sync_with_stdio(false); std::cin.tie(nullptr); tifa_libs::u64 n; std::cin >> n; std::cout << tifa_libs::math::fact_mint<pldt_t>(n); return 0; }