#include #include #include #include #include #include #include #include #include #include #include #include #include template using vc = std::vector; namespace NdVector { template struct ndvector: public std::vector> { static_assert(N > 0, "N should be positive"); using base_tp = ndvector; using base = std::vector; using self = ndvector; template ndvector(T &&n, Ts &&...args): base(n, base_tp(args...)) {} constexpr size_t dim() const { return N; } template void fill(T &&x) { for (auto &i : *this) i.fill(x); } }; template struct ndvector<1, Tp>: public std::vector { using base = std::vector; using self = ndvector<1, Tp>; template ndvector(T &&n): base(n) {} constexpr size_t dim() const { return 1; } template void fill(T &&x) { std::fill(this->begin(), this->end(), x); } }; } // namespace NdVector struct CustomHash { static constexpr uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } static constexpr size_t append(size_t x, size_t y) { return x ^ (y >> 1) ^ ((y & 1) << (sizeof(size_t) * 8 - 1)); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } template size_t operator()(std::pair const &p) const { return append((*this)(p.first), (*this)(p.second)); } template size_t operator()(std::tuple const &tp) const { size_t ret = 0; std::apply( [&](Ts const &...targs) { ((ret = append(ret, (*this)(targs))), ...); }, tp); return ret; } template < class Tp, std::enable_if_t().begin()), typename Tp::iterator>::value && std::is_same().end()), typename Tp::iterator>::value> * = nullptr> size_t operator()(Tp const &tp) const { size_t ret = 0; for (auto &&i : tp) ret = append(ret, (*this)(i)); return ret; } }; using u32 = uint32_t; using i64 = int64_t; #define for_(i, l, r, vars...) \ for (std::make_signed_t i = (l), i##end = (r), ##vars; \ i <= i##end; \ ++i) #define for_step_(i, l, r, s, vars...) \ for (std::make_signed_t i = (l), i##end = (r), ##vars; \ i <= i##end; \ i += s) template constexpr auto chkmin(Tp &a, Tp b) -> bool { return b < a ? a = b, true : false; } template constexpr auto chkmax(Tp &a, Tp b) -> bool { return a < b ? a = b, true : false; } template constexpr auto ispow2(Tp i) -> bool { return i && (i & -i) == i; } #define TPL_SIZE_(Tuple) std::tuple_size_v> namespace tuple_detail_ { template constexpr auto subtuple_impl_(Tuple &&t, std::index_sequence) { return std::make_tuple(std::get(t)...); } template constexpr auto apply2_impl_(BinOp &&f, Tuple &&lhs, Tuple &&rhs, std::index_sequence) { return std::make_tuple( std::forward(f)(std::get(lhs), std::get(rhs))...); } } // namespace tuple_detail_ template constexpr auto subtuple(Tuple &&t) { static_assert(Begin <= TPL_SIZE_(Tuple) && Len <= TPL_SIZE_(Tuple) && Begin + Len <= TPL_SIZE_(Tuple), "Out of range"); return tuple_detail_::subtuple_impl_(t, std::make_index_sequence()); } template constexpr auto tuple_push(Tp &&v, Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), std::make_tuple(v), subtuple(t)); } template constexpr auto tuple_push_front(Tp &&v, Tuple &&t) { return tuple_push<0>(v, t); } template constexpr auto tuple_push_back(Tp &&v, Tuple &&t) { return tuple_push(v, t); } template constexpr auto tuple_pop(Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), subtuple(t)); } template constexpr auto tuple_pop_front(Tuple &&t) { return tuple_pop<0>(t); } template constexpr auto tuple_pop_back(Tuple &&t) { return tuple_pop(t); } template constexpr auto apply2(BinOp &&f, Tuple &&lhs, Tuple &&rhs) { return tuple_detail_::apply2_impl_( f, lhs, rhs, std::make_index_sequence()); } #define OO_PTEQ_(op) \ template \ constexpr auto operator op(std::pair lhs, \ const std::pair &rhs) { \ return std::pair{lhs.first op rhs.first, \ lhs.second op rhs.second}; \ } \ template \ constexpr auto operator op(std::tuple const &lhs, \ std::tuple const &rhs) { \ return apply2([](auto &&l, auto &&r) { return l op r; }, lhs, rhs); \ } \ template \ constexpr std::pair &operator op##=(std::pair &lhs, \ const std::pair &rhs) { \ lhs.first op## = rhs.first; \ lhs.second op## = rhs.second; \ return lhs; \ } \ template \ constexpr auto operator op##=(std::tuple &lhs, \ const std::tuple &rhs) { \ return lhs = lhs op rhs; \ } OO_PTEQ_(+) OO_PTEQ_(-) OO_PTEQ_(*) OO_PTEQ_(/) OO_PTEQ_(%) OO_PTEQ_(&) OO_PTEQ_(|) OO_PTEQ_(^) OO_PTEQ_(<<) OO_PTEQ_(>>) #undef OO_PTEQ_ #undef TPL_SIZE_ template std::istream &operator>>(std::istream &is, std::pair &p) { return is >> p.first >> p.second; } template std::ostream &operator<<(std::ostream &os, const std::pair &p) { return os << p.first << ' ' << p.second; } template std::istream &operator>>(std::istream &is, std::tuple &p) { std::apply([&](Ts &...targs) { ((is >> targs), ...); }, p); return is; } template std::ostream &operator<<(std::ostream &os, const std::tuple &p) { std::apply( [&](Ts const &...targs) { std::size_t n{0}; ((os << targs << (++n != sizeof...(Ts) ? " " : "")), ...); }, p); return os; } template < class Ch, class Tr, class Ct, std::enable_if_t().begin()), typename Ct::iterator>::value && std::is_same().end()), typename Ct::iterator>::value> * = nullptr> std::basic_ostream &operator<<(std::basic_ostream &os, const Ct &x) { if (x.begin() == x.end()) return os; for (auto it = x.begin(); it != x.end() - 1; ++it) os << *it << ' '; os << x.back(); return os; } const u32 OFFSET = 5; const u32 N = 1e6 + OFFSET; const i64 MOD = 32465177; using namespace std; namespace MODINT { constexpr int64_t safe_mod(int64_t x, int64_t m) { return (x %= m) < 0 ? x + m : x; } constexpr std::pair invgcd(int64_t a, int64_t b) { if ((a = safe_mod(a, b)) == 0) return {b, 0}; int64_t s = b, m0 = 0; for (int64_t q = 0, _ = 0, m1 = 1; a;) { _ = s - a * (q = s / a); s = a; a = _; _ = m0 - m1 * q; m0 = m1; m1 = _; } return {s, m0 + (m0 < 0 ? b / s : 0)}; } template class Mint { static_assert(MOD >= 1); using self = Mint; protected: uint32_t v_; public: static constexpr uint32_t mod() { return MOD; } static constexpr self raw(uint32_t v) { self x; x.v_ = v; return x; } constexpr Mint(): v_(0) {} template ::value && std::is_signed::value> * = nullptr> constexpr Mint(T v): Mint() { int64_t x = (int64_t)(v % (int64_t)mod()); v_ = (uint32_t)(x + (x < 0 ? mod() : 0)); } template ::value && std::is_unsigned::value> * = nullptr> constexpr Mint(T v): v_((uint32_t)(v % mod())) {} friend std::istream &operator>>(std::istream &is, self &x) { int64_t xx; is >> xx; xx %= mod(); x.v_ = (uint32_t)(xx + (xx < 0 ? mod() : 0)); return is; } friend std::ostream &operator<<(std::ostream &os, const self &x) { return os << x.v_; } constexpr const uint32_t &val() const { return v_; } constexpr explicit operator uint32_t() const { return val(); } constexpr uint32_t &data() { return v_; } constexpr self &operator++() { if (++v_ == mod()) v_ = 0; return *this; } constexpr self &operator--() { if (!v_) v_ = mod(); --v_; return *this; } constexpr self operator++(int) { self result = *this; ++*this; return result; } constexpr self operator--(int) { self result = *this; --*this; return result; } constexpr self &operator+=(const self &rhs) { v_ += rhs.v_; if (v_ >= mod()) v_ -= mod(); return *this; } constexpr self &operator-=(const self &rhs) { v_ -= rhs.v_; if (v_ >= mod()) v_ += mod(); return *this; } constexpr self &operator*=(const self &rhs) { v_ = (uint32_t)((uint64_t)v_ * rhs.v_ % mod()); return *this; } constexpr self &operator/=(const self &rhs) { return *this = *this * inverse(rhs); } constexpr self operator+() const { return *this; } constexpr self operator-() const { return self() - *this; } constexpr friend self pow(self x, uint64_t y) { self res(1); for (; y; y >>= 1, x *= x) if (y & 1) res *= x; return res; } constexpr friend self inverse(const self &x) { auto &&_ = invgcd(x.v_, self::mod()); if (_.first != 1) throw std::runtime_error("Inverse not exist"); return _.second; } constexpr friend self operator+(self lhs, const self &rhs) { return lhs += rhs; } constexpr friend self operator-(self lhs, const self &rhs) { return lhs -= rhs; } constexpr friend self operator*(self lhs, const self &rhs) { return lhs *= rhs; } constexpr friend self operator/(self lhs, const self &rhs) { return lhs /= rhs; } constexpr friend bool operator==(const self &lhs, const self &rhs) { return lhs.v_ == rhs.v_; } constexpr friend bool operator!=(const self &lhs, const self &rhs) { return lhs.v_ != rhs.v_; } }; } // namespace MODINT using mint = MODINT::Mint; using phimint = MODINT::Mint; namespace primes { vc vis; vc prime; vc h, mu; void init_prime(u32 n) { h.resize(n); mu.resize(n); vis.resize(n); mu[1] = h[1] = 1; for (i64 i = 2; i < n; ++i) { if (!vis[i]) { vis[i] = i; prime.push_back(i); h[i] = 1 - i; mu[i] = -1; } for (auto &&j : prime) { i64 x = i * j; if (x >= n) break; vis[x] = j; if (i % j) { h[x] = h[i] * h[j]; mu[x] = -mu[i]; } else { h[x] = h[i]; break; } } } } } // namespace primes using primes::h, primes::mu; constexpr mint qpow(mint a, phimint b_) { mint res(1); for (i64 b = b_.val(); b; b >>= 1, a *= a) if (b & 1) res *= a; return res; } vc sumhl; vc hh, pdhdkd; void init_(u32 n) { sumhl.resize(n); sumhl[1] = h[1]; for_(i, 2, n - 1) sumhl[i] = sumhl[i - 1] + i * h[i]; hh.resize(n); hh[1] = 1; for_(i, 2, n - 1) hh[i] = hh[i - 1] * qpow(i, i); vc dhd(n); dhd[1] = 1; for_(i, 2, n - 1) dhd[i] = qpow(i, h[i]); vc k(n, 1); for_(i, 2, n - 1) { mint _ = qpow(i, i * mu[i]); for_step_(j, i, n - 1, i) k[j] *= _; } pdhdkd.resize(n); pdhdkd[0] = 1; for_(i, 1, n - 1) pdhdkd[i] = pdhdkd[i - 1] * qpow(dhd[i] * k[i], i); } constexpr phimint s(i64 n) { return n * (n + 1) / 2; } mint calc(i64 n, i64 m) { if (n > m) swap(n, m); mint _ = 1; for (i64 l = 1, r; l <= n; l = r + 1) { r = min(n / (n / l), m / (m / l)); _ *= qpow(hh[n / l], s(m / l) * (sumhl[r] - sumhl[l - 1])) * qpow(hh[m / l], s(n / l) * (sumhl[r] - sumhl[l - 1])) * qpow(pdhdkd[r] / pdhdkd[l - 1], s(n / l) * s(m / l)); } return _; } auto solve([[maybe_unused]] int t_ = 0) -> void { int t, n; cin >> t >> n; primes::init_prime(n + OFFSET); init_(n + OFFSET); while (t--) { int l, r; cin >> l >> r; mint _1 = calc(r, r), _2 = calc(l - 1, l - 1), _3 = calc(r, l - 1); cout << _1 * _2 / (_3 * _3) << '\n'; } } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int i_ = 0; solve(i_); return 0; }