//ACL #ifndef ATCODER_INTERNAL_BITOP_HPP #define ATCODER_INTERNAL_BITOP_HPP 1 #ifdef _MSC_VER #include #include #endif namespace atcoder { namespace internal { int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } int bsf(unsigned int n) { #ifdef _MSC_VER unsigned long index; _BitScanForward(&index, n); return index; #else return __builtin_ctz(n); #endif } } } #endif #ifndef ATCODER_INTERNAL_MATH_HPP #define ATCODER_INTERNAL_MATH_HPP 1 #include namespace atcoder { namespace internal { constexpr long long safe_mod(long long x, long long m) { x %= m; if (x < 0) x += m; return x; } struct barrett { unsigned int _m; unsigned long long im; barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {} unsigned int umod() const { return _m; } unsigned int mul(unsigned int a, unsigned int b) const { unsigned long long z = a; z *= b; #ifdef _MSC_VER unsigned long long x; _umul128(z, im, &x); #else unsigned long long x = (unsigned long long)(((unsigned __int128)(z)*im) >> 64); #endif unsigned int v = (unsigned int)(z - x * _m); if (_m <= v) v += _m; return v; } }; constexpr long long pow_mod_constexpr(long long x, long long n, int m) { if (m == 1) return 0; unsigned int _m = (unsigned int)(m); unsigned long long r = 1; unsigned long long y = safe_mod(x, m); while (n) { if (n & 1) r = (r * y) % _m; y = (y * y) % _m; n >>= 1; } return r; } constexpr bool is_prime_constexpr(int n) { if (n <= 1) return false; if (n == 2 || n == 7 || n == 61) return true; if (n % 2 == 0) return false; long long d = n - 1; while (d % 2 == 0) d /= 2; int v[] = { 2,7,61 }; for (long long a : v) { long long t = d; long long y = pow_mod_constexpr(a, t, n); while (t != n - 1 && y != 1 && y != n - 1) { y = y * y % n; t <<= 1; } if (y != n - 1 && t % 2 == 0) { return false; } } return true; } template constexpr bool is_prime = is_prime_constexpr(n); constexpr std::pair inv_gcd(long long a, long long b) { a = safe_mod(a, b); if (a == 0) return { b, 0 }; long long s = b, t = a; long long m0 = 0, m1 = 1; while (t) { long long u = s / t; s -= t * u; m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b auto tmp = s; s = t; t = tmp; tmp = m0; m0 = m1; m1 = tmp; } if (m0 < 0) m0 += b / s; return { s, m0 }; } constexpr int primitive_root_constexpr(int m) { if (m == 2) return 1; if (m == 167772161) return 3; if (m == 469762049) return 3; if (m == 754974721) return 11; if (m == 998244353) return 3; int divs[20] = {}; divs[0] = 2; int cnt = 1; int x = (m - 1) / 2; while (x % 2 == 0) x /= 2; for (int i = 3; (long long)(i)*i <= x; i += 2) { if (x % i == 0) { divs[cnt++] = i; while (x % i == 0) { x /= i; } } } if (x > 1) { divs[cnt++] = x; } for (int g = 2;; g++) { bool ok = true; for (int i = 0; i < cnt; i++) { if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) { ok = false; break; } } if (ok) return g; } } template constexpr int primitive_root = primitive_root_constexpr(m); } } #endif #ifndef ATCODER_INTERNAL_QUEUE_HPP #define ATCODER_INTERNAL_QUEUE_HPP 1 #include namespace atcoder { namespace internal { template struct simple_queue { std::vector payload; int pos = 0; void reserve(int n) { payload.reserve(n); } int size() const { return int(payload.size()) - pos; } bool empty() const { return pos == int(payload.size()); } void push(const T& t) { payload.push_back(t); } T& front() { return payload[pos]; } void clear() { payload.clear(); pos = 0; } void pop() { pos++; } }; } } #endif #ifndef ATCODER_INTERNAL_SCC_HPP #define ATCODER_INTERNAL_SCC_HPP 1 #include #include #include namespace atcoder { namespace internal { template struct csr { std::vector start; std::vector elist; csr(int n, const std::vector>& edges) : start(n + 1), elist(edges.size()) { for (auto e : edges) { start[e.first + 1]++; } for (int i = 1; i <= n; i++) { start[i] += start[i - 1]; } auto counter = start; for (auto e : edges) { elist[counter[e.first]++] = e.second; } } }; struct scc_graph { public: scc_graph(int n) : _n(n) {} int num_vertices() { return _n; } void add_edge(int from, int to) { edges.push_back({ from, {to} }); } std::pair> scc_ids() { auto g = csr(_n, edges); int now_ord = 0, group_num = 0; std::vector visited, low(_n), ord(_n, -1), ids(_n); visited.reserve(_n); auto dfs = [&](auto self, int v) -> void { low[v] = ord[v] = now_ord++; visited.push_back(v); for (int i = g.start[v]; i < g.start[v + 1]; i++) { auto to = g.elist[i].to; if (ord[to] == -1) { self(self, to); low[v] = std::min(low[v], low[to]); } else { low[v] = std::min(low[v], ord[to]); } } if (low[v] == ord[v]) { while (true) { int u = visited.back(); visited.pop_back(); ord[u] = _n; ids[u] = group_num; if (u == v) break; } group_num++; } }; for (int i = 0; i < _n; i++) { if (ord[i] == -1) dfs(dfs, i); } for (auto& x : ids) { x = group_num - 1 - x; } return { group_num, ids }; } std::vector> scc() { auto ids = scc_ids(); int group_num = ids.first; std::vector counts(group_num); for (auto x : ids.second) counts[x]++; std::vector> groups(ids.first); for (int i = 0; i < group_num; i++) { groups[i].reserve(counts[i]); } for (int i = 0; i < _n; i++) { groups[ids.second[i]].push_back(i); } return groups; } private: int _n; struct edge { int to; }; std::vector> edges; }; } } #endif #ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP #define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1 #include #include #include namespace atcoder { namespace internal { #ifndef _MSC_VER template using is_signed_int128 = typename std::conditional::value || std::is_same::value, std::true_type, std::false_type>::type; template using is_unsigned_int128 = typename std::conditional::value || std::is_same::value, std::true_type, std::false_type>::type; template using make_unsigned_int128 = typename std::conditional::value, __uint128_t, unsigned __int128>; template using is_integral = typename std::conditional::value || is_signed_int128::value || is_unsigned_int128::value, std::true_type, std::false_type>::type; template using is_signed_int = typename std::conditional<(is_integral::value&& std::is_signed::value) || is_signed_int128::value, std::true_type, std::false_type>::type; template using is_unsigned_int = typename std::conditional<(is_integral::value&& std::is_unsigned::value) || is_unsigned_int128::value, std::true_type, std::false_type>::type; template using to_unsigned = typename std::conditional< is_signed_int128::value, make_unsigned_int128, typename std::conditional::value, std::make_unsigned, std::common_type>::type>::type; #else template using is_integral = typename std::is_integral; template using is_signed_int = typename std::conditional::value&& std::is_signed::value, std::true_type, std::false_type>::type; template using is_unsigned_int = typename std::conditional::value&& std::is_unsigned::value, std::true_type, std::false_type>::type; template using to_unsigned = typename std::conditional::value, std::make_unsigned, std::common_type>::type; #endif template using is_signed_int_t = std::enable_if_t::value>; template using is_unsigned_int_t = std::enable_if_t::value>; template using to_unsigned_t = typename to_unsigned::type; } } #endif #ifndef ATCODER_MODINT_HPP #define ATCODER_MODINT_HPP 1 #include #include #include #ifdef _MSC_VER #include #endif namespace atcoder { namespace internal { struct modint_base {}; struct static_modint_base : modint_base {}; template using is_modint = std::is_base_of; template using is_modint_t = std::enable_if_t::value>; } template * = nullptr> struct static_modint : internal::static_modint_base { using mint = static_modint; public: static constexpr int mod() { return m; } static mint raw(int v) { mint x; x._v = v; return x; } static_modint() : _v(0) {} template * = nullptr> static_modint(T v) { long long x = (long long)(v % (long long)(umod())); if (x < 0) x += umod(); _v = (unsigned int)(x); } template * = nullptr> static_modint(T v) { _v = (unsigned int)(v % umod()); } static_modint(bool v) { _v = ((unsigned int)(v) % umod()); } unsigned int val() const { return _v; } mint& operator++() { _v++; if (_v == umod()) _v = 0; return *this; } mint& operator--() { if (_v == 0) _v = umod(); _v--; return *this; } mint operator++(int) { mint result = *this; ++*this; return result; } mint operator--(int) { mint result = *this; --*this; return result; } mint& operator+=(const mint& rhs) { _v += rhs._v; if (_v >= umod()) _v -= umod(); return *this; } mint& operator-=(const mint& rhs) { _v -= rhs._v; if (_v >= umod()) _v += umod(); return *this; } mint& operator*=(const mint& rhs) { unsigned long long z = _v; z *= rhs._v; _v = (unsigned int)(z % umod()); return *this; } mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); } mint operator+() const { return *this; } mint operator-() const { return mint() - *this; } mint pow(long long n) const { assert(0 <= n); mint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } mint inv() const { if (prime) { assert(_v); return pow(umod() - 2); } else { auto eg = internal::inv_gcd(_v, m); assert(eg.first == 1); return eg.second; } } friend mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; } friend mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; } friend mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; } friend mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; } friend bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; } friend bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; } private: unsigned int _v; static constexpr unsigned int umod() { return m; } static constexpr bool prime = internal::is_prime; }; template struct dynamic_modint : internal::modint_base { using mint = dynamic_modint; public: static int mod() { return (int)(bt.umod()); } static void set_mod(int m) { assert(1 <= m); bt = internal::barrett(m); } static mint raw(int v) { mint x; x._v = v; return x; } dynamic_modint() : _v(0) {} template * = nullptr> dynamic_modint(T v) { long long x = (long long)(v % (long long)(mod())); if (x < 0) x += mod(); _v = (unsigned int)(x); } template * = nullptr> dynamic_modint(T v) { _v = (unsigned int)(v % mod()); } dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); } unsigned int val() const { return _v; } mint& operator++() { _v++; if (_v == umod()) _v = 0; return *this; } mint& operator--() { if (_v == 0) _v = umod(); _v--; return *this; } mint operator++(int) { mint result = *this; ++*this; return result; } mint operator--(int) { mint result = *this; --*this; return result; } mint& operator+=(const mint& rhs) { _v += rhs._v; if (_v >= umod()) _v -= umod(); return *this; } mint& operator-=(const mint& rhs) { _v += mod() - rhs._v; if (_v >= umod()) _v -= umod(); return *this; } mint& operator*=(const mint& rhs) { _v = bt.mul(_v, rhs._v); return *this; } mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); } mint operator+() const { return *this; } mint operator-() const { return mint() - *this; } mint pow(long long n) const { assert(0 <= n); mint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } mint inv() const { auto eg = internal::inv_gcd(_v, mod()); assert(eg.first == 1); return eg.second; } friend mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; } friend mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; } friend mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; } friend mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; } friend bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; } friend bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; } private: unsigned int _v; static internal::barrett bt; static unsigned int umod() { return bt.umod(); } }; template internal::barrett dynamic_modint::bt = 998244353; using modint998244353 = static_modint<998244353>; using modint1000000007 = static_modint<1000000007>; using modint = dynamic_modint<-1>; namespace internal { template using is_static_modint = std::is_base_of; template using is_static_modint_t = std::enable_if_t::value>; template struct is_dynamic_modint : public std::false_type {}; template struct is_dynamic_modint> : public std::true_type {}; template using is_dynamic_modint_t = std::enable_if_t::value>; } } #endif #ifndef ATCODER_CONVOLUTION_HPP #define ATCODER_CONVOLUTION_HPP 1 #include #include #include #include #include namespace atcoder { namespace internal { template * = nullptr> void butterfly(std::vector& a) { static constexpr int g = internal::primitive_root; int n = int(a.size()); int h = internal::ceil_pow2(n); static bool first = true; static mint sum_e[30]; if (first) { first = false; mint es[30], ies[30]; int cnt2 = bsf(mint::mod() - 1); mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv(); for (int i = cnt2; i >= 2; i--) { // e^(2^i) == 1 es[i - 2] = e; ies[i - 2] = ie; e *= e; ie *= ie; } mint now = 1; for (int i = 0; i < cnt2 - 2; i++) { sum_e[i] = es[i] * now; now *= ies[i]; } } for (int ph = 1; ph <= h; ph++) { int w = 1 << (ph - 1), p = 1 << (h - ph); mint now = 1; for (int s = 0; s < w; s++) { int offset = s << (h - ph + 1); for (int i = 0; i < p; i++) { auto l = a[i + offset]; auto r = a[i + offset + p] * now; a[i + offset] = l + r; a[i + offset + p] = l - r; } now *= sum_e[bsf(~(unsigned int)(s))]; } } } template * = nullptr> void butterfly_inv(std::vector& a) { static constexpr int g = internal::primitive_root; int n = int(a.size()); int h = internal::ceil_pow2(n); static bool first = true; static mint sum_ie[30]; if (first) { first = false; mint es[30], ies[30]; int cnt2 = bsf(mint::mod() - 1); mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv(); for (int i = cnt2; i >= 2; i--) { // e^(2^i) == 1 es[i - 2] = e; ies[i - 2] = ie; e *= e; ie *= ie; } mint now = 1; for (int i = 0; i < cnt2 - 2; i++) { sum_ie[i] = ies[i] * now; now *= es[i]; } } for (int ph = h; ph >= 1; ph--) { int w = 1 << (ph - 1), p = 1 << (h - ph); mint inow = 1; for (int s = 0; s < w; s++) { int offset = s << (h - ph + 1); for (int i = 0; i < p; i++) { auto l = a[i + offset]; auto r = a[i + offset + p]; a[i + offset] = l + r; a[i + offset + p] = (unsigned long long)(mint::mod() + l.val() - r.val()) * inow.val(); } inow *= sum_ie[bsf(~(unsigned int)(s))]; } } } } template * = nullptr> std::vector convolution(std::vector a, std::vector b) { int n = int(a.size()), m = int(b.size()); if (!n || !m) return {}; if (std::min(n, m) <= 60) { if (n < m) { std::swap(n, m); std::swap(a, b); } std::vector ans(n + m - 1); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { ans[i + j] += a[i] * b[j]; } } return ans; } int z = 1 << internal::ceil_pow2(n + m - 1); a.resize(z); internal::butterfly(a); b.resize(z); internal::butterfly(b); for (int i = 0; i < z; i++) { a[i] *= b[i]; } internal::butterfly_inv(a); a.resize(n + m - 1); mint iz = mint(z).inv(); for (int i = 0; i < n + m - 1; i++) a[i] *= iz; return a; } template ::value>* = nullptr> std::vector convolution(const std::vector& a, const std::vector& b) { int n = int(a.size()), m = int(b.size()); if (!n || !m) return {}; using mint = static_modint; std::vector a2(n), b2(m); for (int i = 0; i < n; i++) { a2[i] = mint(a[i]); } for (int i = 0; i < m; i++) { b2[i] = mint(b[i]); } auto c2 = convolution(move(a2), move(b2)); std::vector c(n + m - 1); for (int i = 0; i < n + m - 1; i++) { c[i] = c2[i].val(); } return c; } std::vector convolution_ll(const std::vector& a, const std::vector& b) { int n = int(a.size()), m = int(b.size()); if (!n || !m) return {}; static constexpr unsigned long long MOD1 = 754974721; static constexpr unsigned long long MOD2 = 167772161; static constexpr unsigned long long MOD3 = 469762049; static constexpr unsigned long long M2M3 = MOD2 * MOD3; static constexpr unsigned long long M1M3 = MOD1 * MOD3; static constexpr unsigned long long M1M2 = MOD1 * MOD2; static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3; static constexpr unsigned long long i1 = internal::inv_gcd(MOD2 * MOD3, MOD1).second; static constexpr unsigned long long i2 = internal::inv_gcd(MOD1 * MOD3, MOD2).second; static constexpr unsigned long long i3 = internal::inv_gcd(MOD1 * MOD2, MOD3).second; auto c1 = convolution(a, b); auto c2 = convolution(a, b); auto c3 = convolution(a, b); std::vector c(n + m - 1); for (int i = 0; i < n + m - 1; i++) { unsigned long long x = 0; x += (c1[i] * i1) % MOD1 * M2M3; x += (c2[i] * i2) % MOD2 * M1M3; x += (c3[i] * i3) % MOD3 * M1M2; long long diff = c1[i] - internal::safe_mod((long long)(x), (long long)(MOD1)); if (diff < 0) diff += MOD1; static constexpr unsigned long long offset[5] = { 0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3 }; x -= offset[diff % 5]; c[i] = x; } return c; } } #endif #ifndef ATCODER_DSU_HPP #define ATCODER_DSU_HPP 1 #include #include #include namespace atcoder { struct dsu { public: dsu() : _n(0) {} dsu(int n) : _n(n), parent_or_size(n, -1) {} int merge(int a, int b) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); int x = leader(a), y = leader(b); if (x == y) return x; if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y); parent_or_size[x] += parent_or_size[y]; parent_or_size[y] = x; return x; } bool same(int a, int b) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); return leader(a) == leader(b); } int leader(int a) { assert(0 <= a && a < _n); if (parent_or_size[a] < 0) return a; return parent_or_size[a] = leader(parent_or_size[a]); } int size(int a) { assert(0 <= a && a < _n); return -parent_or_size[leader(a)]; } std::vector> groups() { std::vector leader_buf(_n), group_size(_n); for (int i = 0; i < _n; i++) { leader_buf[i] = leader(i); group_size[leader_buf[i]]++; } std::vector> result(_n); for (int i = 0; i < _n; i++) { result[i].reserve(group_size[i]); } for (int i = 0; i < _n; i++) { result[leader_buf[i]].push_back(i); } result.erase( std::remove_if(result.begin(), result.end(), [&](const std::vector& v) { return v.empty(); }), result.end()); return result; } private: int _n; std::vector parent_or_size; }; } #endif #ifndef ATCODER_FENWICKTREE_HPP #define ATCODER_FENWICKTREE_HPP 1 #include #include namespace atcoder { template struct fenwick_tree { using U = internal::to_unsigned_t; public: fenwick_tree() : _n(0) {} fenwick_tree(int n) : _n(n), data(n) {} void add(int p, T x) { assert(0 <= p && p < _n); p++; while (p <= _n) { data[p - 1] += U(x); p += p & -p; } } T sum(int l, int r) { assert(0 <= l && l <= r && r <= _n); return sum(r) - sum(l); } private: int _n; std::vector data; U sum(int r) { U s = 0; while (r > 0) { s += data[r - 1]; r -= r & -r; } return s; } }; } #endif #ifndef ATCODER_LAZYSEGTREE_HPP #define ATCODER_LAZYSEGTREE_HPP 1 #include #include #include #include namespace atcoder { template struct lazy_segtree { public: lazy_segtree() : lazy_segtree(0) {} lazy_segtree(int n) : lazy_segtree(std::vector(n, e())) {} lazy_segtree(const std::vector& v) : _n(int(v.size())) { log = internal::ceil_pow2(_n); size = 1 << log; d = std::vector(2 * size, e()); lz = std::vector(size, id()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); return d[p]; } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); if (l == r) return e(); l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push(r >> i); } S sml = e(), smr = e(); while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } void apply(int p, F f) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = mapping(f, d[p]); for (int i = 1; i <= log; i++) update(p >> i); } void apply(int l, int r, F f) { assert(0 <= l && l <= r && r <= _n); if (l == r) return; l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } { int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l >>= 1; r >>= 1; } l = l2; r = r2; } for (int i = 1; i <= log; i++) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } template int max_right(int l) { return max_right(l, [](S x) { return g(x); }); } template int max_right(int l, G g) { assert(0 <= l && l <= _n); assert(g(e())); if (l == _n) return _n; l += size; for (int i = log; i >= 1; i--) push(l >> i); S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!g(op(sm, d[l]))) { while (l < size) { push(l); l = (2 * l); if (g(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template int min_left(int r) { return min_left(r, [](S x) { return g(x); }); } template int min_left(int r, G g) { assert(0 <= r && r <= _n); assert(g(e())); if (r == 0) return 0; r += size; for (int i = log; i >= 1; i--) push((r - 1) >> i); S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!g(op(d[r], sm))) { while (r < size) { push(r); r = (2 * r + 1); if (g(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector d; std::vector lz; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } void all_apply(int k, F f) { d[k] = mapping(f, d[k]); if (k < size) lz[k] = composition(f, lz[k]); } void push(int k) { all_apply(2 * k, lz[k]); all_apply(2 * k + 1, lz[k]); lz[k] = id(); } }; } #endif #ifndef ATCODER_MATH_HPP #define ATCODER_MATH_HPP 1 #include #include #include #include namespace atcoder { long long pow_mod(long long x, long long n, int m) { assert(0 <= n && 1 <= m); if (m == 1) return 0; internal::barrett bt((unsigned int)(m)); unsigned int r = 1, y = (unsigned int)(internal::safe_mod(x, m)); while (n) { if (n & 1) r = bt.mul(r, y); y = bt.mul(y, y); n >>= 1; } return r; } long long inv_mod(long long x, long long m) { assert(1 <= m); auto z = internal::inv_gcd(x, m); assert(z.first == 1); return z.second; } std::pair crt(const std::vector& r, const std::vector& m) { assert(r.size() == m.size()); int n = int(r.size()); long long r0 = 0, m0 = 1; for (int i = 0; i < n; i++) { assert(1 <= m[i]); long long r1 = internal::safe_mod(r[i], m[i]), m1 = m[i]; if (m0 < m1) { std::swap(r0, r1); std::swap(m0, m1); } if (m0 % m1 == 0) { if (r0 % m1 != r1) return { 0, 0 }; continue; } long long g, im; std::tie(g, im) = internal::inv_gcd(m0, m1); long long u1 = (m1 / g); if ((r1 - r0) % g) return { 0, 0 }; long long x = (r1 - r0) / g % u1 * im % u1; r0 += x * m0; m0 *= u1; if (r0 < 0) r0 += m0; } return { r0, m0 }; } long long floor_sum(long long n, long long m, long long a, long long b) { long long ans = 0; if (a >= m) { ans += (n - 1) * n * (a / m) / 2; a %= m; } if (b >= m) { ans += n * (b / m); b %= m; } long long y_max = (a * n + b) / m, x_max = (y_max * m - b); if (y_max == 0) return ans; ans += (n - (x_max + a - 1) / a) * y_max; ans += floor_sum(y_max, a, m, (a - x_max % a) % a); return ans; } } #endif #ifndef ATCODER_MAXFLOW_HPP #define ATCODER_MAXFLOW_HPP 1 #include #include #include #include #include namespace atcoder { template struct mf_graph { public: mf_graph() : _n(0) {} mf_graph(int n) : _n(n), g(n) {} int add_edge(int from, int to, Cap cap) { assert(0 <= from && from < _n); assert(0 <= to && to < _n); assert(0 <= cap); int m = int(pos.size()); pos.push_back({ from, int(g[from].size()) }); g[from].push_back(_edge{ to, int(g[to].size()), cap }); g[to].push_back(_edge{ from, int(g[from].size()) - 1, 0 }); return m; } struct edge { int from, to; Cap cap, flow; }; edge get_edge(int i) { int m = int(pos.size()); assert(0 <= i && i < m); auto _e = g[pos[i].first][pos[i].second]; auto _re = g[_e.to][_e.rev]; return edge{ pos[i].first, _e.to, _e.cap + _re.cap, _re.cap }; } std::vector edges() { int m = int(pos.size()); std::vector result; for (int i = 0; i < m; i++) { result.push_back(get_edge(i)); } return result; } void change_edge(int i, Cap new_cap, Cap new_flow) { int m = int(pos.size()); assert(0 <= i && i < m); assert(0 <= new_flow && new_flow <= new_cap); auto& _e = g[pos[i].first][pos[i].second]; auto& _re = g[_e.to][_e.rev]; _e.cap = new_cap - new_flow; _re.cap = new_flow; } Cap flow(int s, int t) { return flow(s, t, std::numeric_limits::max()); } Cap flow(int s, int t, Cap flow_limit) { assert(0 <= s && s < _n); assert(0 <= t && t < _n); std::vector level(_n), iter(_n); internal::simple_queue que; auto bfs = [&]() { std::fill(level.begin(), level.end(), -1); level[s] = 0; que.clear(); que.push(s); while (!que.empty()) { int v = que.front(); que.pop(); for (auto e : g[v]) { if (e.cap == 0 || level[e.to] >= 0) continue; level[e.to] = level[v] + 1; if (e.to == t) return; que.push(e.to); } } }; auto dfs = [&](auto self, int v, Cap up) { if (v == s) return up; Cap res = 0; int level_v = level[v]; for (int& i = iter[v]; i < int(g[v].size()); i++) { _edge& e = g[v][i]; if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue; Cap d = self(self, e.to, std::min(up - res, g[e.to][e.rev].cap)); if (d <= 0) continue; g[v][i].cap += d; g[e.to][e.rev].cap -= d; res += d; if (res == up) break; } return res; }; Cap flow = 0; while (flow < flow_limit) { bfs(); if (level[t] == -1) break; std::fill(iter.begin(), iter.end(), 0); while (flow < flow_limit) { Cap f = dfs(dfs, t, flow_limit - flow); if (!f) break; flow += f; } } return flow; } std::vector min_cut(int s) { std::vector visited(_n); internal::simple_queue que; que.push(s); while (!que.empty()) { int p = que.front(); que.pop(); visited[p] = true; for (auto e : g[p]) { if (e.cap && !visited[e.to]) { visited[e.to] = true; que.push(e.to); } } } return visited; } private: int _n; struct _edge { int to, rev; Cap cap; }; std::vector> pos; std::vector> g; }; } #endif #ifndef ATCODER_MINCOSTFLOW_HPP #define ATCODER_MINCOSTFLOW_HPP 1 #include #include #include #include #include namespace atcoder { template struct mcf_graph { public: mcf_graph() {} mcf_graph(int n) : _n(n), g(n) {} int add_edge(int from, int to, Cap cap, Cost cost) { assert(0 <= from && from < _n); assert(0 <= to && to < _n); int m = int(pos.size()); pos.push_back({ from, int(g[from].size()) }); g[from].push_back(_edge{ to, int(g[to].size()), cap, cost }); g[to].push_back(_edge{ from, int(g[from].size()) - 1, 0, -cost }); return m; } struct edge { int from, to; Cap cap, flow; Cost cost; }; edge get_edge(int i) { int m = int(pos.size()); assert(0 <= i && i < m); auto _e = g[pos[i].first][pos[i].second]; auto _re = g[_e.to][_e.rev]; return edge{ pos[i].first, _e.to, _e.cap + _re.cap, _re.cap, _e.cost, }; } std::vector edges() { int m = int(pos.size()); std::vector result(m); for (int i = 0; i < m; i++) { result[i] = get_edge(i); } return result; } std::pair flow(int s, int t) { return flow(s, t, std::numeric_limits::max()); } std::pair flow(int s, int t, Cap flow_limit) { return slope(s, t, flow_limit).back(); } std::vector> slope(int s, int t) { return slope(s, t, std::numeric_limits::max()); } std::vector> slope(int s, int t, Cap flow_limit) { assert(0 <= s && s < _n); assert(0 <= t && t < _n); assert(s != t); std::vector dual(_n, 0), dist(_n); std::vector pv(_n), pe(_n); std::vector vis(_n); auto dual_ref = [&]() { std::fill(dist.begin(), dist.end(), std::numeric_limits::max()); std::fill(pv.begin(), pv.end(), -1); std::fill(pe.begin(), pe.end(), -1); std::fill(vis.begin(), vis.end(), false); struct Q { Cost key; int to; bool operator<(Q r) const { return key > r.key; } }; std::priority_queue que; dist[s] = 0; que.push(Q{ 0, s }); while (!que.empty()) { int v = que.top().to; que.pop(); if (vis[v]) continue; vis[v] = true; if (v == t) break; for (int i = 0; i < int(g[v].size()); i++) { auto e = g[v][i]; if (vis[e.to] || !e.cap) continue; Cost cost = e.cost - dual[e.to] + dual[v]; if (dist[e.to] - dist[v] > cost) { dist[e.to] = dist[v] + cost; pv[e.to] = v; pe[e.to] = i; que.push(Q{ dist[e.to], e.to }); } } } if (!vis[t]) { return false; } for (int v = 0; v < _n; v++) { if (!vis[v]) continue; dual[v] -= dist[t] - dist[v]; } return true; }; Cap flow = 0; Cost cost = 0, prev_cost = -1; std::vector> result; result.push_back({ flow, cost }); while (flow < flow_limit) { if (!dual_ref()) break; Cap c = flow_limit - flow; for (int v = t; v != s; v = pv[v]) { c = std::min(c, g[pv[v]][pe[v]].cap); } for (int v = t; v != s; v = pv[v]) { auto& e = g[pv[v]][pe[v]]; e.cap -= c; g[v][e.rev].cap += c; } Cost d = -dual[s]; flow += c; cost += c * d; if (prev_cost == d) { result.pop_back(); } result.push_back({ flow, cost }); prev_cost = cost; } return result; } private: int _n; struct _edge { int to, rev; Cap cap; Cost cost; }; std::vector> pos; std::vector> g; }; } #endif #ifndef ATCODER_SCC_HPP #define ATCODER_SCC_HPP 1 #include #include #include namespace atcoder { struct scc_graph { public: scc_graph() : internal(0) {} scc_graph(int n) : internal(n) {} void add_edge(int from, int to) { int n = internal.num_vertices(); assert(0 <= from && from < n); assert(0 <= to && to < n); internal.add_edge(from, to); } std::vector> scc() { return internal.scc(); } private: internal::scc_graph internal; }; } #endif #ifndef ATCODER_SEGTREE_HPP #define ATCODER_SEGTREE_HPP 1 #include #include #include namespace atcoder { template struct segtree { public: segtree() : segtree(0) {} segtree(int n) : segtree(std::vector(n, e())) {} segtree(const std::vector& v) : _n(int(v.size())) { log = internal::ceil_pow2(_n); size = 1 << log; d = std::vector(2 * size, e()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); return d[p + size]; } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); S sml = e(), smr = e(); l += size; r += size; while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } template int max_right(int l) { return max_right(l, [](S x) { return f(x); }); } template int max_right(int l, F f) { assert(0 <= l && l <= _n); assert(f(e())); if (l == _n) return _n; l += size; S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!f(op(sm, d[l]))) { while (l < size) { l = (2 * l); if (f(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template int min_left(int r) { return min_left(r, [](S x) { return f(x); }); } template int min_left(int r, F f) { assert(0 <= r && r <= _n); assert(f(e())); if (r == 0) return 0; r += size; S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!f(op(d[r], sm))) { while (r < size) { r = (2 * r + 1); if (f(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector d; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } }; } #endif #ifndef ATCODER_STRING_HPP #define ATCODER_STRING_HPP 1 #include #include #include #include #include namespace atcoder { namespace internal { std::vector sa_naive(const std::vector& s) { int n = int(s.size()); std::vector sa(n); std::iota(sa.begin(), sa.end(), 0); std::sort(sa.begin(), sa.end(), [&](int l, int r) { if (l == r) return false; while (l < n && r < n) { if (s[l] != s[r]) return s[l] < s[r]; l++; r++; } return l == n; }); return sa; } std::vector sa_doubling(const std::vector& s) { int n = int(s.size()); std::vector sa(n), rnk = s, tmp(n); std::iota(sa.begin(), sa.end(), 0); for (int k = 1; k < n; k *= 2) { auto cmp = [&](int x, int y) { if (rnk[x] != rnk[y]) return rnk[x] < rnk[y]; int rx = x + k < n ? rnk[x + k] : -1; int ry = y + k < n ? rnk[y + k] : -1; return rx < ry; }; std::sort(sa.begin(), sa.end(), cmp); tmp[sa[0]] = 0; for (int i = 1; i < n; i++) { tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0); } std::swap(tmp, rnk); } return sa; } template std::vector sa_is(const std::vector& s, int upper) { int n = int(s.size()); if (n == 0) return {}; if (n == 1) return { 0 }; if (n == 2) { if (s[0] < s[1]) { return { 0, 1 }; } else { return { 1, 0 }; } } if (n < THRESHOLD_NAIVE) { return sa_naive(s); } if (n < THRESHOLD_DOUBLING) { return sa_doubling(s); } std::vector sa(n); std::vector ls(n); for (int i = n - 2; i >= 0; i--) { ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]); } std::vector sum_l(upper + 1), sum_s(upper + 1); for (int i = 0; i < n; i++) { if (!ls[i]) { sum_s[s[i]]++; } else { sum_l[s[i] + 1]++; } } for (int i = 0; i <= upper; i++) { sum_s[i] += sum_l[i]; if (i < upper) sum_l[i + 1] += sum_s[i]; } auto induce = [&](const std::vector& lms) { std::fill(sa.begin(), sa.end(), -1); std::vector buf(upper + 1); std::copy(sum_s.begin(), sum_s.end(), buf.begin()); for (auto d : lms) { if (d == n) continue; sa[buf[s[d]]++] = d; } std::copy(sum_l.begin(), sum_l.end(), buf.begin()); sa[buf[s[n - 1]]++] = n - 1; for (int i = 0; i < n; i++) { int v = sa[i]; if (v >= 1 && !ls[v - 1]) { sa[buf[s[v - 1]]++] = v - 1; } } std::copy(sum_l.begin(), sum_l.end(), buf.begin()); for (int i = n - 1; i >= 0; i--) { int v = sa[i]; if (v >= 1 && ls[v - 1]) { sa[--buf[s[v - 1] + 1]] = v - 1; } } }; std::vector lms_map(n + 1, -1); int m = 0; for (int i = 1; i < n; i++) { if (!ls[i - 1] && ls[i]) { lms_map[i] = m++; } } std::vector lms; lms.reserve(m); for (int i = 1; i < n; i++) { if (!ls[i - 1] && ls[i]) { lms.push_back(i); } } induce(lms); if (m) { std::vector sorted_lms; sorted_lms.reserve(m); for (int v : sa) { if (lms_map[v] != -1) sorted_lms.push_back(v); } std::vector rec_s(m); int rec_upper = 0; rec_s[lms_map[sorted_lms[0]]] = 0; for (int i = 1; i < m; i++) { int l = sorted_lms[i - 1], r = sorted_lms[i]; int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n; int end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n; bool same = true; if (end_l - l != end_r - r) { same = false; } else { while (l < end_l) { if (s[l] != s[r]) { break; } l++; r++; } if (l == n || s[l] != s[r]) same = false; } if (!same) rec_upper++; rec_s[lms_map[sorted_lms[i]]] = rec_upper; } auto rec_sa = sa_is(rec_s, rec_upper); for (int i = 0; i < m; i++) { sorted_lms[i] = lms[rec_sa[i]]; } induce(sorted_lms); } return sa; } } std::vector suffix_array(const std::vector& s, int upper) { assert(0 <= upper); for (int d : s) { assert(0 <= d && d <= upper); } auto sa = internal::sa_is(s, upper); return sa; } template std::vector suffix_array(const std::vector& s) { int n = int(s.size()); std::vector idx(n); iota(idx.begin(), idx.end(), 0); sort(idx.begin(), idx.end(), [&](int l, int r) { return s[l] < s[r]; }); std::vector s2(n); int now = 0; for (int i = 0; i < n; i++) { if (i && s[idx[i - 1]] != s[idx[i]]) now++; s2[idx[i]] = now; } return internal::sa_is(s2, now); } std::vector suffix_array(const std::string& s) { int n = int(s.size()); std::vector s2(n); for (int i = 0; i < n; i++) { s2[i] = s[i]; } return internal::sa_is(s2, 255); } template std::vector lcp_array(const std::vector& s, const std::vector& sa) { int n = int(s.size()); assert(n >= 1); std::vector rnk(n); for (int i = 0; i < n; i++) { rnk[sa[i]] = i; } std::vector lcp(n - 1); int h = 0; for (int i = 0; i < n; i++) { if (h > 0) h--; if (rnk[i] == 0) continue; int j = sa[rnk[i] - 1]; for (; j + h < n && i + h < n; h++) { if (s[j + h] != s[i + h]) break; } lcp[rnk[i] - 1] = h; } return lcp; } std::vector lcp_array(const std::string& s, const std::vector& sa) { int n = int(s.size()); std::vector s2(n); for (int i = 0; i < n; i++) { s2[i] = s[i]; } return lcp_array(s2, sa); } template std::vector z_algorithm(const std::vector& s) { int n = int(s.size()); if (n == 0) return {}; std::vector z(n); z[0] = 0; for (int i = 1, j = 0; i < n; i++) { int& k = z[i]; k = (j + z[j] <= i) ? 0 : std::min(j + z[j] - i, z[i - j]); while (i + k < n && s[k] == s[i + k]) k++; if (j + z[j] < i + z[i]) j = i; } z[0] = n; return z; } std::vector z_algorithm(const std::string& s) { int n = int(s.size()); std::vector s2(n); for (int i = 0; i < n; i++) { s2[i] = s[i]; } return z_algorithm(s2); } } #endif #ifndef ATCODER_TWOSAT_HPP #define ATCODER_TWOSAT_HPP 1 #include #include namespace atcoder { struct two_sat { public: two_sat() : _n(0), scc(0) {} two_sat(int n) : _n(n), _answer(n), scc(2 * n) {} void add_clause(int i, bool f, int j, bool g) { assert(0 <= i && i < _n); assert(0 <= j && j < _n); scc.add_edge(2 * i + (f ? 0 : 1), 2 * j + (g ? 1 : 0)); scc.add_edge(2 * j + (g ? 0 : 1), 2 * i + (f ? 1 : 0)); } bool satisfiable() { auto id = scc.scc_ids().second; for (int i = 0; i < _n; i++) { if (id[2 * i] == id[2 * i + 1]) return false; _answer[i] = id[2 * i] < id[2 * i + 1]; } return true; } std::vector answer() { return _answer; } private: int _n; std::vector _answer; internal::scc_graph scc; }; } #endif //ACL end #pragma warning(disable:4996) #include using namespace std; using namespace atcoder; using mint = static_modint<1000000007>; using vmint = vector; using vvmint = vector; using vvvmint = vector; using vvvvmint = vector; istream& operator>>(istream& is, mint& a) { long long v; is >> v; a = v; return is; } ostream& operator<<(ostream& os, mint a) { return os << a.val(); } #ifdef _MSC_VER #include #define __builtin_popcount __popcnt #define __builtin_popcountll __popcnt64 #endif template using vec = vector; using ll = long long; using ull = unsigned long long; using stirng = string; using itn = int; using vs = vec; using vc = vec; using vvc = vec; using vvvc = vec; using vi = vec; using vvi = vec; using vvvi = vec; using vvvvi = vec; using vll = vec; using vvll = vec; using vvvll = vec; using vvvvll = vec; using si = set; using vsi = vec; using vvsi = vec; using vvvsi = vec; using sll = set; using vsll = vec; using vvsll = vec; using vvvsll = vec; using vd = vec; using vvd = vec; using vvvd = vec; using vvvvd = vec; using pii = pair; using pll = pair; using pd = pair; using mii = map; using mll = map; using msi = multiset; using msll = multiset; using vpii = vec; using vvpii = vec; using vvvpii = vec; using vpll = vec; using vvpll = vec; using vvvpll = vec; using vpd = vec; using spii = set; using spll = set; using spd = set; using vspll = vec; using vvspll = vec; using vb = vec; using vvb = vec; using vvvb = vec; #define rep(i,j,n) for(ll i=j;i<(n);i++) #define rrep(i,j,n) for (ll i = (n)-1; i >=j; i--) #define Call_4th(_1, _2, _3, _4, ...) _4 #define rp(...) Call_4th(__VA_ARGS__, _1, rp2)(__VA_ARGS__) #define rp2(i, n) rep(i, 0, n) #define rrp(i,n) rrep(i,0,(n)) #define all(v) v.begin(), v.end() #define pb push_back #define pp pop_back() #define bk back() #define ins insert #define yes cout<<"Yes"< int len(T& x) { return int(x.size()); } #define sz size() #define fi first #define se second #define nxp next_permutation ll mod0 = 998244353, lmax = 4e18, inf = 1050000000; double pi = 3.141592653589793238462643; //cin系統 template void in(T&... X) { (cin >> ... >> X); } template void ain(vec& Y) { rp(K, Y.size()) cin >> Y[K]; } template void ain(set& Y, auto n) { rp(i, n) { T YY; cin >> YY; Y.insert(YY); } } template void ain(multiset& Y, auto n) { rp(i, n) { T YY; cin >> YY; Y.insert(YY); } } template void ain(pair& a) { cin >> a.fi >> a.se; } template void bin(vec& Z) { rp(L, Z.size()) ain(Z[L]); } //cout系統 // vector template struct is_vector : false_type {}; template struct is_vector> : true_type {}; // queue template struct is_queue : false_type {}; template struct is_queue> : true_type {}; // stack template struct is_stack : false_type {}; template struct is_stack> : true_type {}; // pair template struct is_pair : false_type {}; template struct is_pair> : true_type {}; // set / multiset template struct is_set_like : false_type {}; template struct is_set_like> : true_type {}; template struct is_set_like> : true_type {}; // map / multimap template struct is_map_like : false_type {}; template struct is_map_like> : true_type {}; template struct is_map_like> : true_type {}; template void aout(const T& x) { if constexpr (is_vector::value) { for (const auto& e : x) aout(e); cout << endl; } else if constexpr (is_queue::value) { auto copy = x; while (!copy.empty()) { aout(copy.front()); copy.pop(); } cout << endl; } else if constexpr (is_stack::value) { auto copy = x; while (!copy.empty()) { aout(copy.top()); copy.pop(); } cout << endl; } else if constexpr (is_pair::value) { aout(x.first); aout(x.second); cout << endl; } else if constexpr (is_set_like::value) { for (const auto& e : x) aout(e); cout << endl; } else if constexpr (is_map_like::value) { for (const auto& e : x) aout(e); // pair cout << endl; } else { cout << x << " "; } } //数学系 ll modcnt(ll l, ll r, ll m, ll a) {//l以上r以下の整数iでi≡a(mod m)となるものの個数(l>r,a<0等も可) assert(m != 0); m = abs(m); ll x = l + ((a - l) % m + m) % m;//l以上で最小のi≡a(mod m)となるi if (x > r) return 0; return (r - x) / m + 1; } ll dsum(ll a) {//桁和 ll r = 0; while (a != 0) { r += a % 10; a /= 10; } return r; } ll dnum(ll a) {//桁数(0は0桁) ll r = 0; while (a != 0) { r++; a /= 10; } return r; } sll yk(ll n) {//約数全列挙O(sqrt(N)),set sll yaku; for (ll i = 1; i * i <= n; i++) if (n % i == 0) { yaku.insert(i); yaku.insert(n / i); } return yaku; } vi ssa(int n) {//n:必要な素数の最大値 素数全列挙 線形篩 vector prime; vectorlpf(n + 1, 0);//最小素因数 rep(i, 2, n + 1) { if (lpf[i] == 0) { lpf[i] = i; prime.push_back(i); } for (int k : prime) { if (k * i > n || k > lpf[i]) break;//k最小素因数よりk<=i lpf[k * i] = k;//kを最小素因数に持つ数k*iを拾う } } return prime; } vector sib(ll x) {//素因数分解 if (x == 1) return vector(1, { 1,1 }); vector ans; for (ll i = 2; i * i <= x; i++) {//rootx回iを回しxで割る ll kaisu = 0; while (x % i == 0) { x /= i; kaisu++; } if (kaisu > 0) ans.pb({ i,kaisu }); } if (x != 1) ans.pb({ x,1 }); return ans; } bool isp(ll x) {//素数判定 O(sqrt(x)) auto y = sib(x); return (x != 1 && y.sz == 1 && y[0] == pll{ x, 1 }); } vec> sib(ll x, ll y) {//閉区間[x,y]全素因数分解 x=1は何も返さない O(max(sqrt(y),y-x)loglogy) ABC227G ABC412E vi b = ssa(sqrt(y) + 100); vec> r(y - x + 1); vll num(y - x + 1); rp(i, y - x + 1) num[i] = x + i; for (ll k : b) for (ll a = (1 + (x - 1) / k) * k; a <= y; a += k) { ll kaisu = 0; while (num[a - x] % k == 0) { num[a - x] /= k; kaisu++; } if (kaisu) r[a - x].pb({ k,kaisu }); } rp(i, y - x + 1) if (num[i] != 1) r[i].pb({ num[i],1 }); return r; } template ll sqrtll(T a) {//整数sqrt a<0orr非整数の場合-1を返す if (a < 0) return -1; ll r = sqrt(a); while (r * r > a) r--; while ((r + 1) * (r + 1) <= a) r++; if (r * r == a)return r; else return -1; } #define llsqrt sqrtll ll powll(ll a, ll b) {//llでpow ll c = 1; assert(pow(a, b) <= 9e18); rp(i, b) { c *= a; } return c; } #define llpow powll template T sq(T a) {//2乗 return a * a; } template T cb(T a) {//3乗 return a * a * a; } string basea(ll x, ll a) {//xをa進法に変換 string r; while (x != 0) { r.pb(x % a + '0'); x /= a; } reverse(all(r)); return r; } ll base10(string x, ll a) {//a進数のxを10進法に戻す ll r = 0; rp(i, x.sz) { r *= a; r += x[i] - '0'; } return r; } vll vbasea(ll x, ll a) {//xをa進法に変換(vector) vll r; while (x != 0) { r.pb(x % a); x /= a; } reverse(all(r)); return r; } template ll bc(T x) {//bitcount assert(x >= 0); return __builtin_popcount(x); } double ds(double x1, double x2, double y1, double y2) {//dist return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } ll ds2(ll x1, ll x2, ll y1, ll y2) {//distの2乗(整数値) return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); } template ll ds2(vec a) { return (a[0] - a[2]) * (a[0] - a[2]) + (a[1] - a[3]) * (a[1] - a[3]); } ll gpsum(ll a, ll r, ll n, ll m) {//初項a,公比r,項数nの等比数列の総和mod m r=10でレピュニットも可能 if (n == 0) return 0; if (n == 1) return a % m; modint::set_mod(m); if (n % 2 == 1) return (a + gpsum(a * r % m, r, n - 1, m)) % m; else return ((modint(r).pow(n / 2) + 1) * gpsum(a, r, n / 2, m)).val(); } //二分探索 template auto lwa(typename std::vector::iterator b, typename std::vector::iterator e, T c) {//[b,e)でcより小さい最大の値のイテレータ(複数あれば右端) auto it = std::lower_bound(b, e, c); if (it == b) return e; --it; return it; } template auto lwa(vector& a, T b) {//aでbより小さい最大の値のイテレータ(複数あれば右端) return lwa(all(a), b); } template auto lwa(set& a, T b) {//aでbより小さい最大の値のイテレータ(複数あれば右端) auto i = a.lwb(b); if (i == a.begin()) return a.end(); else i--; return i; } template auto lwa(multiset& a, T b) {//aでbより小さい最大の値のイテレータ(複数あれば右端) auto i = a.lwb(b); if (i == a.begin()) return a.end(); else i--; return i; } template auto lwc(typename std::vector::iterator b, typename std::vector::iterator e, T c) {//aでb以下の最大の値のイテレータ(複数あれば左端) auto i = lwb(b, e, c); if (i != e && *i == c) return i; if (i == b) return e; else i--; return i; } template auto lwc(vector& a, T b) {//aでb以下の最大の値のイテレータ(複数あれば左端) return lwc(all(a), b); } template auto lwc(set& a, T b) {//aでb以下の最大の値のイテレータ(複数あれば左端) auto i = a.lwb(b); if (i != a.end() && *i == b) return i; if (i == a.begin()) return a.end(); else i--; return i; } template auto lwc(multiset& a, T b) {//aでb以下の最大の値のイテレータ(複数あれば左端) auto i = a.lwb(b); if (i != a.end() && *i == b) return i; if (i == a.begin()) return a.end(); else i--; return i; } template std::pair::iterator, typename vector::iterator> its(vec& v, T a) {//{--lwb,lwb}({x未満の右端,x以上の左端})のpair返す(なければend()) auto it = lwb(all(v), a); if (it == v.begin()) return { v.end(), it }; auto it2 = it; it2--; return { it2,it }; } template std::pair::iterator, typename set::iterator> its(set& v, T a) {//{--lwb,lwb}({x未満の右端,x以上の左端})のpair返す(なければend()) auto it = v.lwb(a); if (it == v.begin()) return { v.end(), it }; auto it2 = it; it2--; return { it2,it }; } template std::pair::iterator, typename multiset::iterator> its(multiset& v, T a) {//{--lwb,lwb}({x未満の右端,x以上の左端})のpair返す(なければend()) auto it = v.lwb(a); if (it == v.begin()) return { v.end(), it }; auto it2 = it; it2--; return { it2,it }; } template typename vector::iterator nits(vec& v, T a, bool isr = 1) {//itsのうちaに近い方返す(距離同じの場合isr==0なら左優先,1なら右優先) v.sz==0のときv.end()返す auto cd = its(v, a); if (cd.fi == v.end()) return cd.se; if (cd.se == v.end()) return cd.fi; auto l = a - *cd.fi, r = *cd.se - a; if (l < r) return cd.fi; if (l > r || isr == 1) return cd.se; return cd.fi; } template typename set::iterator nits(set& v, T a, bool isr = 1) {//itsのうちaに近い方返す(距離同じの場合isr==0なら左優先,1なら右優先) v.sz==0のときv.end()返す auto cd = its(v, a); if (cd.fi == v.end()) return cd.se; if (cd.se == v.end()) return cd.fi; auto l = a - *cd.fi, r = *cd.se - a; if (l < r) return cd.fi; if (l > r || isr == 1) return cd.se; return cd.fi; } template typename multiset::iterator nits(multiset& v, T a, bool isr = 1) {//itsのうちaに近い方返す(距離同じの場合isr==0なら左優先,1なら右優先) v.sz==0のときv.end()返す auto cd = its(v, a); if (cd.fi == v.end()) return cd.se; if (cd.se == v.end()) return cd.fi; auto l = a - *cd.fi, r = *cd.se - a; if (l < r) return cd.fi; if (l > r || isr == 1) return cd.se; return cd.fi; } template int rcount(vec& a, T l, T r) {//ソート済配列aから[l,r]の範囲(l以上r以下)の要素カウント //右端を超える最小のi-左端に引っかかる最小のi //l,rのどちらに対しても境界を含む/含まないを入れ替えるときupb/lwbを変えれば良い return upb(all(a), r) - lwb(all(a), l); } template int rcount(set& a, T l, T r) {//ソート済配列aから[l,r]の範囲(l以上r以下)の要素カウント return a.upb(r) - a.lwb(l); } template bool has(const Container& c, const Key& x) {//sort済vector/set/map等に対しその値を持つかどうか返す if constexpr (is_set_like::value || is_map_like::value) { // set / multiset / map return c.find(x) != c.end(); } else { // vector 等(ソート済前提) return std::binary_search(c.begin(), c.end(), x); } } //配列便利関数系 template bool chmin(T& M1, T M2) { if (M1 > M2) { M1 = M2; return 1; } else return 0; } template bool chmax(T& M1, T M2) { if (M1 < M2) { M1 = M2; return 1; } else return 0; } template auto vmax(T a) { return *max_element(all(a)); } template auto vmin(T a) { return *min_element(all(a)); } template auto vmaxi(T a) { return max_element(all(a)) - a.begin(); } template auto vmini(T a) { return min_element(all(a)) - a.begin(); } template auto vsum(vector a) { T x = 0; for (auto i : a)x += i; return x; } template vec inv(vec a) {//0-indexed 逆関数 vec ans(a.sz); rp(i, a.sz) { ans[a[i]] = i; } return ans; } template vec inv1(vec a) {//1-indexed vec ans(a.sz); rp(i, a.sz) { ans[a[i] - 1] = i + 1; } return ans; } template vec zat(vec a) {//座標圧縮 T=ll,int auto b = a; sort(all(b)); b.erase(unique(all(b)), b.end()); vec c(a.size()); rp(i, a.size()) { c[i] = lwb(all(b), a[i]) - b.begin(); } return c; } template vec rsw(vec a, bool is_put0 = 1) {//累積和 T=ll,int if (is_put0 == 0) { vec b = {}; rp(i, a.sz) b.pb(a[i] + (b.sz == 0 ? 0 : b[b.sz - 1])); return b; } vec b = { 0 }; rp(i, a.sz) b.pb(a[i] + b[b.sz - 1]); return b; } template T rswsum(vec& a, int l, int r, bool is_put0 = 1) {//rsw配列から元の配列の[l,r)番目(0indexed)の和を取得 if (is_put0 == 0) { assert(0 <= l && l <= r); assert(r <= a.sz); return (r == 0 ? 0 : a[r - 1]) - (l == 0 ? 0 : a[l - 1]); } assert(0 <= l && l <= r); assert(r < a.sz); return a[r] - a[l]; } template T rswsum2(vec& a, int l, int r, bool is_put0 = 1) {//rsw配列から元の配列の[l,r]番目(0indexed)の和を取得 return rswsum(a, l, r + 1, is_put0); } //文字列系 vector> rle(string rr) { vector> ret; char lc; rep(i, 0, rr.size()) { if (i > 0 && rr[i] == lc) ret[ret.sz - 1].second++; else { ret.pb({ rr[i],1 }); } lc = rr[i]; } return ret; } vector> rle(vi rr) { vector> ret; int lc; rep(i, 0, rr.size()) { if (i > 0 && rr[i] == lc) ret[ret.sz - 1].second++; else { ret.pb({ rr[i],1 }); } lc = rr[i]; } return ret; } vector> rle(vll rr) { vector> ret; ll lc; rep(i, 0, rr.size()) { if (i > 0 && rr[i] == lc) ret[ret.sz - 1].second++; else { ret.pb({ rr[i],1 }); } lc = rr[i]; } return ret; } bool kai(string S) {//回文か判定 bool ans = 1; rp(i, S.size()) if (S[i] != S[S.size() - 1 - i]) ans = 0; return ans; } template string concat(const Args&... args) {//任意個のchat・string・int等を引数に取り文字列として繋げたstringを返す(整数はasciiでcharに変換) string res; (res += ... += args); return res; } //その他 ll max(ll a, int b) { return max(a, ll(b)); } ll max(int a, ll b) { return max(ll(a), b); } ll min(ll a, int b) { return min(a, ll(b)); } ll min(int a, ll b) { return min(ll(a), b); } bool yn(bool jg) { if (jg) { cout << "Yes" << endl; return true; } else { cout << "No" << endl; return false; } } bool ynab(bool jg) { if (jg) { cout << "Alice" << endl; return true; } else { cout << "Bob" << endl; return false; } } template void cp(map < T, ll >& a, T b, ll c) {//countplus if (a.find(b) == a.end()) a[b] = c; else a[b] += c; if (a[b] == 0) a.erase(b); } template bool cross(T a, T b, T c, T d) {//区間(a,b)と区間(c,d)が重なるか判定 return !(b <= c || d <= a); } template bool crosse(T a, T b, T c, T d) {//区間[a,b]と区間[c,d]が重なるか判定 return !(b < c || d < a); } template vec absort(vec a, vec b) {//l,rのl昇順r逆順sort vec> ab(a.sz); rp(i, a.sz) ab[i] = { a[i],-b[i],i }; sort(all(ab)); rp(i, a.sz) ab[i][1] = -ab[i][1]; return ab; } template bool rabc(T a, T b, T c) {//円環状でa,b,cがこの順か判定 同じ値はfalse return ((a - b) / abs(a - b)) * ((b - c) / abs(b - c)) * ((c - a) / abs(c - a)) > 0; } bool labc(ll a, ll b, ll c) {//a<=b> rot(vs a) {//時計回り90度回転 vector> r(a[0].sz, vector(a.sz)); rp(i, a.sz)rp(j, a[0].sz) r[j][a[0].sz - 1 - i] = a[i][j]; return r; } template vector> rot(vector> a) { vector> r(a[0].sz, vector(a.sz)); rp(i, a.sz)rp(j, a[0].sz) r[j][a.sz - 1 - i] = a[i][j]; return r; } //実行時間調整付きassert std::chrono::steady_clock::time_point START_TIME; void start() { START_TIME = std::chrono::steady_clock::now(); } void assertt(bool b, int t) { if (b) return; if (START_TIME.time_since_epoch().count() == 0) { start(); } auto target_time = START_TIME + std::chrono::milliseconds(t - 100); while (std::chrono::steady_clock::now() < target_time); assert(0); } bool testt(int t) {//tミリ秒経っていないならtrue (while(testt(1950))のように使う) assert(START_TIME.time_since_epoch().count() != 0); auto target_time = START_TIME + std::chrono::milliseconds(t - 100); return (std::chrono::steady_clock::now() < target_time); } //lazy_segtree seg(n); //S:中身型 op:左右合成 e:初期値 //F:遅延型 mapping:遅延適用後の要素 composition:遅延合成( 関数f(g()) ) id:遅延初期値(何もさせない) using S = ll; using F = ll; S op(S a, S b) { return max(a, b); } S e() { return -lmax; } using segt = segtree; /* S mapping(F x, S a) {//xをaに作用(x初期値に注意) S[l]~S[r]のopであるSにF適用するとF(S[l])~F(S[r])のopになる必要がある 、つまりL~Rの代表にFかけてもL~Rの代表であり続けられるようS作る必要がある if(x==0) return a; else return {a.se,a.se}; } F composition(F f, F g) {//fの方が後(f初期値に注意) Fを何個合成しても1つのFで表せる if(f==0 && g==0 )return 0; return 1; } F id() { return 0; } using lsegt = lazy_segtree; */ //cout< 関数名 = [&](引数の型1 引数名1, 引数の型2, 引数名2, ...) //function f=[&](int a,int b) //再帰しない場合 auto f=[&](int a,int b) ->ll{} int mxkj;//階乗に入れる値の最大値 vector kj, gkj; bool iskjset = 0; void kjset(int maxkj) { iskjset = 1; mxkj = maxkj; kj.resize(mxkj + 1); gkj.resize(mxkj + 1); kj[0] = 1;//階乗 rep(i, 1, mxkj + 1) { kj[i] = kj[i - 1] * i; } gkj[mxkj] = 1 / kj[mxkj]; rrp(i, mxkj) gkj[i] = gkj[i + 1] * (i + 1); } auto cmb = [](int fst, int snd) { assert(iskjset); bool ck = 1;//範囲外値でエラーを返すなら1(ck=0でもpowの引数など他の値が範囲外にならないか要確認) if (0 <= fst && fst <= mxkj && 0 <= snd && snd <= fst); else { if (ck) assert(0); else return mint(0); } return kj[fst] * gkj[snd] * gkj[fst - snd]; }; auto pmt = [](int fst, int snd) { assert(iskjset); bool ck = 1;//範囲外値でエラーを返すなら1(ck=0でもpowの引数など他の値が範囲外にならないか要確認) if (0 <= fst && fst <= mxkj && 0 <= snd && snd <= fst); else { if (ck) assert(0); else return mint(0); } return kj[fst] * gkj[fst - snd]; }; vec conv_sp(vmint a, vmint sp, ll mxi = 200100) {//疎な場合のconv高速化 aの長さN,spの非0係数K個としてO(NK) vec> sps; int spmxi = -1; rp(i, sp.size()) { if (sp[i] != 0) { sps.pb({ i,sp[i] }); spmxi = i; } } if (spmxi == -1) return { 0 }; vmint r(min(mxi, ll(a.sz) + spmxi), 0); rp(i, a.sz) { for (auto j : sps) { if (i + j.fi < mxi)r[i + j.fi] += j.se * a[i]; } } return r; } vec div_sp(vmint f, vmint sp, ll mxi = 200100) {//f/spをmxiまで計算 ただしspのx^0項非0 spの非0係数K個としてO(mxiK) assert(sp.sz > 0 && sp[0] != 0); vec> sps; int spmxi = -1; rp(i, sp.size()) { if (sp[i] != 0) { sps.pb({ i,sp[i] }); spmxi = i; } } vec r(mxi, 0); f.resize(mxi); mint gsp0 = 1 / sp[0]; rp(i, mxi) { r[i] = f[i] * gsp0; for (auto j : sps) { if (i + j.fi < mxi)f[i + j.fi] -= r[i] * j.se; } } return r; } vec conv(vmint a, vmint b, ll mxi = 200100) {//a.sz+b.sz=nとしてO(nlogn) a.sz+b.sz>2^23=8.3e6を超えると畳み込み不可能 if (a.sz > mxi) a.resize(mxi); if (b.sz > mxi) b.resize(mxi); vmint r = convolution(a, b); if (r.size() > mxi) r.resize(mxi); return r; } mint convget(vmint a, vmint b, ll i) {//conv(a,b)[i]をO(a.sz+b.sz+i)で求める if (i < 0) return 0; mint r = 0; rp(ii, i + 1) { if (ii < a.sz && i - ii < b.sz)r += a[ii] * b[i - ii]; } return r; } vec vinv(vmint f, ll mxi = 200100) {// O(mxi・logmxi) assert(f.sz > 0 && f[0] != 0); vec g = { mint(1) / f[0] }; f.resize(mxi); // fを最初にリサイズ for (ll len = 1; len < mxi; len <<= 1) {//g←g(2-fg)をlog(mxi)回 int need = min(mxi, len << 1); auto fg = conv(vec(f.begin(), f.begin() + need), g, need); // f * g for (int i = 0; i < need; i++) fg[i] = -fg[i]; fg[0] += 2; // 2 - f*g g = conv(g, fg, need); } return g; } vmint log(vmint f, ll mxi = 200100) {//log(f)を求める(ただしf[0]=1が必要) O(mxi・logmxi) ∫(f')/f if (f.sz > mxi) f.resize(mxi); assert(f[0] == 1); if (f.sz == 1) return { 0 }; vmint bf(f.sz - 1);//fの微分 rp(i, f.sz - 1) bf[i] = f[i + 1] * (i + 1); vmint bg = conv(bf, vinv(f, mxi), mxi); vmint g(bg.sz); g[0] = 0; rp(i, bg.sz - 1) g[i + 1] = bg[i] / (i + 1); return g; } vmint exp(vmint f, ll mxi = 200100) {//exp(f)をニュートン法で求める(ただしf[0]=0が必要) O(mxi・logmxi) assert(f[0] == 0); vec g = { 1 }; f.resize(mxi); // fを最初にリサイズ for (ll len = 1; len < mxi; len <<= 1) {//g←g(1-log(g)+f)をlog(mxi)回 int need = min(mxi, len << 1); vmint x = log(g, need); x.resize(need); rp(i, need) x[i] = f[i] - x[i]; x[0]++; g = conv(g, x, need); } return g; } vec vpow(vmint a, ll p, ll mxi = 200100) {//a[0]+a[1]x+a[2]x^2...のp乗をa^p=exp(log(a))を利用して計算 O(mxi・logmxi) int d = 0;//前から何個0が続くか rp(i, a.sz) { if (a[i] == 0) d++; else break; } assert(p >= 0 || d == 0);//p<0かつd>0は計算不能(FPSで定義されない) if (p == 0 || double(d) * p >= mxi || d == a.sz) {//0乗 or all zero vmint r(mxi, 0); if (p == 0) r[0] = 1; return r; } //a[0]=1になるように前d個の0を消し、a全体をa[0]で割る補正 mint c = 1, ad = 1; if (a[d] != 1) { ad = a[d]; c = 1 / a[d]; rp(i, a.sz) a[i] *= c; } if (d > 0) { rp(i, a.sz - d)a[i] = a[i + d]; a.resize(a.sz - d); } vmint ploga = log(a, mxi - d * p);//p*log(a) rp(i, ploga.sz) ploga[i] *= p; vmint r = exp(ploga, mxi - d * p); mint adp;//ad^p if (p < 0) adp = mint(c).pow(-p); else adp = ad.pow(p); rp(i, r.sz) r[i] *= adp; r.resize(mxi); rrp(i, mxi) { if (i < d * p)r[i] = 0; else r[i] = r[i - d * p]; } return r; } vec vap(vvmint a, ll mxi = 200100) {//多項式総積 次数の総和NとしてO(N(logN)^2) if (a.sz == 0) return { 1 }; queue q; for (auto& i : a) q.push(i); while (q.sz > 1) { vmint p1 = q.front(); q.pop(); vmint p2 = q.front(); q.pop(); vmint np = conv(p1, p2, mxi); q.push(np); } return q.front(); } vec vquot(vmint g, vmint f) {//多項式除算 N次g,M次fに対してg=qf+r(m-1次以下)を満たすqをO(NlogN)で求める while (f.sz > 0 && f[f.sz - 1] == 0) f.pop_back(); assert(f.sz != 0); while (g.sz > 0 && g[g.sz - 1] == 0) g.pop_back(); if (g.sz < f.sz) return {}; int n = int(g.sz) - 1, m = int(f.sz) - 1; vmint revg = g; reverse(all(revg)); vmint revf = f; reverse(all(revf)); vmint revq = conv(revg, vinv(revf, n - m + 1), n - m + 1); revq.resize(n - m + 1); reverse(all(revq));//ここでrevqがqを表すようになる return revq; } vec vmod(vmint g, vmint f) {//多項式の余り N次g,M次fに対してg=qf+r(m-1次以下)を満たすrをO(NlogN)で求める while (f.sz > 0 && f[f.sz - 1] == 0) f.pop_back(); assert(f.sz != 0); vmint q = vquot(g, f); vmint qf = conv(q, f, f.sz - 1); vmint r(f.sz - 1); g.resize(f.sz - 1); qf.resize(f.sz - 1); rp(i, f.sz - 1) { r[i] = g[i] - qf[i]; } while (r.sz > 0 && r[r.sz - 1] == 0) r.pop_back(); return r; } vec vpowmod(vmint g, vmint f, ll p) {//多項式の余り g^p mod f f,gの次数NとしてO(NlogNlogp) vmint r = { 1 }; assert(p < (ll(1) << 60)); rrp(i, 60) { r = conv(r, r, 2 * r.sz); r = vmod(r, f); if (p & (ll(1) << i)) { r = conv(r, g, r.sz + g.sz); r = vmod(r, f); } } return r; } vec vplus(vmint f, vmint g) {//f+g if (f.sz > g.sz) swap(f, g); vmint r(g.sz, 0); rp(i, f.sz) r[i] = f[i] + g[i]; rep(i, f.sz, g.sz) r[i] = g[i]; return r; } mint vdn(vmint f, mint a) {//f(x)にaを代入(f(a)を計算) mint r = 0; rp(i, f.sz) r += f[i] * a.pow(i); return r; } vec v1pow(ll p, ll mxi = 200100) {//(1/(1-x))={1,1,1,...}^pをmxiまでO(mxi)で求める p+mxiまでkjの前計算が必要 gkjが求まっていない場合はO(mxi・log998) assert(p + mxi - 1 <= mxkj); if (p == 0) { vmint r(mxi, 0); r[0] = 1; return r; } vmint r(mxi); rp(i, mxi) r[i] = cmb(p + i - 1, i); return r; } vec v1apow(mint a, ll p, ll mxi = 200100) {//(1+ax)^pをmxiまでa==1でO(mxi),a!=1でO(mxi・logp)で求める mxiまでkjの前計算が必要 gkjが求まっていない場合はO(mxi・log998) assert(mxi <= mxkj); vmint r(mxi, 0); ll siz = min(mxi, p + 1); if (a == 1) rp(i, siz) { r[i] = cmb(p, i); } else rp(i, siz) { r[i] = cmb(p, i) * a.pow(i); } return r; } template mint parsum(vec a, T s) {//部分和問題 配列aから0個以上選んで和をsにする通り数 aの総和xとしてO(x(logx)^2) if (s < 0) return 0; int n = a.sz; vvmint p(n); rp(i, n) { p[i] = vmint(a[i] + 1, 0); p[i][0] = 1; p[i][a[i]] += 1; } vmint ans = vap(p, s + 1); if (ans.sz <= s)return 0; return ans[s]; } vmint apowsum(vmint a, ll m) {//長さNの配列aに対しΣ(a[i]^k)をk=0,1,2...Mに対してO(N(logN)^2+MlogM)で列挙 int n = a.sz; vvmint x(n); rp(i, n) x[i] = { 1,-a[i] }; vmint y = vap(x, n + 1); y = log(y, m + 1); rp(i, y.sz) y[i] = -y[i] * i; y[0] = n; return y; } vec ktms(vmint d, ll n) {//a.sz=d.sz=kとして aの漸化式ai=d_0*a_(i-1)+...+d_(k-1)*a_(i-k)のときa_n=x0a0+...+x_(k-1)a_(k-1)を満たす配列xをO(KlogKlogN) int k = d.sz; reverse(all(d)); vmint q(k + 1); rp(i, k) q[i] = -d[i]; q[k] = 1; vmint r = vpowmod({ 0,1 }, q, n); r.resize(k); return r; } mint bm(vmint p, vmint q, ll n) {// bostan-mori [x^n] P(x)/Q(x)をP,Qの次数KとしてO(KlogKlogN) if (p.sz != 0) p.pb(0); if (n == 0) return p[0] / q[0]; vmint mq = q; for (int i = 0; i < mq.sz; i += 2) mq[i] = -mq[i]; vmint u = conv(p, mq, p.sz + mq.sz), v2 = conv(q, mq, q.sz + mq.sz); vmint v; for (int i = 0; i < v2.sz; i += 2) v.pb(v2[i]); if (n % 2 == 0) { vmint ue; for (int i = 0; i < u.sz; i += 2) ue.pb(u[i]); return bm(ue, v, n / 2); } else { vmint ue; for (int i = 1; i < u.sz; i += 2) ue.pb(u[i]); return bm(ue, v, n / 2); } } mint tobm(vmint a, vmint d, ll n) {//a.sz=d.sz=kとして aの漸化式ai=d_0*a_(i-1)+...+d_(k-1)*a_(i-k)のときa_n=x0a0+...+x_(k-1)a_(k-1)をO(KlogKlogN) assert(a.sz == d.sz); ll k = a.sz; vmint q = { 1 }; for (auto i : d) q.pb(-i); vmint p = conv(a, q, k); return bm(p, q, n); } //Berlekamp–Massey aの漸化式ai=d_0*a_(i-1)+...+d_(k-1)*a_(i-k)のとき配列{1,-d_0,-d_1,...}をa.sz=NとしてO(N^2) //L=q.sz(q:返り値)としてN<2*Lなら解は複数存在 2*L<=Nなら解は唯一 //qに対して末尾の0を削除してはならない vmint bm2(vmint a) { vmint q = { 1 },b=q; int l = 0, pn = -1; mint pd = 1; rp(n, a.sz) { mint d = 0; rp(j, n + 1) if(j bmbm(vmint a,ll k){ pair r; vmint q = bm2(a); if (q.sz * 2 <= a.sz) r.fi = true; else r.fi = false; r.se = bm(conv(a, q, q.sz), q, k); return r; } int main() { ll a, b, c, d, e, n; cin >> a >> b >> c >> d >> e >> n; vmint f(10); f[0] = a; f[1] = b; rep(i, 2, 10) f[i] = c * f[i - 1] + d * f[i - 2] + e; f = rsw(f, 0); auto ans = bmbm(f, n); cout << ans.se << endl; }