This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub maspypy/library
#include "mod/floor_monoid_product.hpp"
#include "alg/monoid_pow.hpp" // https://yukicoder.me/submissions/883884 // https://qoj.ac/contest/1411/problem/7620 // U は範囲内で ax+b がオーバーフローしない程度 // yyy x yyyy x ... yyy x yyy (x を N 個) // k 個目の x までに floor(ak+b,m) 個の y がある // my<=ax+b における lattice path における辺の列と見なせる template <typename Monoid, typename X, typename U> X floor_monoid_product(X x, X y, U N, U a, U b, U m) { U c = (a * N + b) / m; X pre = Monoid::unit(), suf = Monoid::unit(); while (1) { const U p = a / m, q = b / m; a %= m, b %= m; x = Monoid::op(x, monoid_pow<Monoid>(y, p)); pre = Monoid::op(pre, monoid_pow<Monoid>(y, q)); c -= (p * N + q); if (c == 0) break; const U d = (m * c - b - 1) / a + 1; suf = Monoid::op(y, Monoid::op(monoid_pow<Monoid>(x, N - d), suf)); b = m - b - 1 + a, N = c - 1, c = d; swap(m, a), swap(x, y); } x = monoid_pow<Monoid>(x, N); return Monoid::op(Monoid::op(pre, x), suf); }
#line 2 "alg/monoid_pow.hpp" // chat gpt template <typename U, typename Arg1, typename Arg2> struct has_power_method { private: // ヘルパー関数の実装 template <typename V, typename A1, typename A2> static auto check(int) -> decltype(std::declval<V>().power(std::declval<A1>(), std::declval<A2>()), std::true_type{}); template <typename, typename, typename> static auto check(...) -> std::false_type; public: // メソッドの有無を表す型 static constexpr bool value = decltype(check<U, Arg1, Arg2>(0))::value; }; template <typename Monoid> typename Monoid::X monoid_pow(typename Monoid::X x, ll exp) { using X = typename Monoid::X; if constexpr (has_power_method<Monoid, X, ll>::value) { return Monoid::power(x, exp); } else { assert(exp >= 0); X res = Monoid::unit(); while (exp) { if (exp & 1) res = Monoid::op(res, x); x = Monoid::op(x, x); exp >>= 1; } return res; } } #line 2 "mod/floor_monoid_product.hpp" // https://yukicoder.me/submissions/883884 // https://qoj.ac/contest/1411/problem/7620 // U は範囲内で ax+b がオーバーフローしない程度 // yyy x yyyy x ... yyy x yyy (x を N 個) // k 個目の x までに floor(ak+b,m) 個の y がある // my<=ax+b における lattice path における辺の列と見なせる template <typename Monoid, typename X, typename U> X floor_monoid_product(X x, X y, U N, U a, U b, U m) { U c = (a * N + b) / m; X pre = Monoid::unit(), suf = Monoid::unit(); while (1) { const U p = a / m, q = b / m; a %= m, b %= m; x = Monoid::op(x, monoid_pow<Monoid>(y, p)); pre = Monoid::op(pre, monoid_pow<Monoid>(y, q)); c -= (p * N + q); if (c == 0) break; const U d = (m * c - b - 1) / a + 1; suf = Monoid::op(y, Monoid::op(monoid_pow<Monoid>(x, N - d), suf)); b = m - b - 1 + a, N = c - 1, c = d; swap(m, a), swap(x, y); } x = monoid_pow<Monoid>(x, N); return Monoid::op(Monoid::op(pre, x), suf); }