#line 1 "a.cpp" // https://qandori.github.io/cp-library/ // #include #include using namespace std; using std::cerr, std::cin, std::cout; #define vec vector typedef long double ld; #if LONG_MAX == 2147483647L #undef long #define long long long #endif #define uint unsigned int #define ulong unsigned long #define overload3(a, b, c, name, ...) name #define rep3(i, a, b) for (int i = (a); i < (b); i++) #define rep2(i, n) rep3(i, 0, n) #define rep1(n) rep2(__i__, n) #define rep(...) overload3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__) #define per3(i, a, b) for (int i = (b) - 1; i >= (a); i--) #define per2(i, n) per3(i, 0, n) #define per1(n) per2(__i__, n) #define per(...) overload3(__VA_ARGS__, per3, per2, per1)(__VA_ARGS__) #define all(a) a.begin(), a.end() #define UNIQUE(a) sort(all(a)), a.erase(unique(all(a)), a.end()), a.shrink_to_fit() #define sz(a) static_cast(a.size()) #ifndef DEBUG #define cerr \ if (false) cerr #undef endl #define endl '\n' #endif inline auto operator^=(vector::reference a, bool b) noexcept { if (b) a.flip(); return a; } inline auto operator&=(vector::reference a, bool b) noexcept { if (!b) a = false; return a; } inline auto operator|=(vector::reference a, bool b) noexcept { if (b) a = true; return a; } inline ostream &operator<<(ostream &os, __int128_t value) { ostream::sentry s(os); if (s) { __uint128_t tmp = value; if (value < 0) tmp = -tmp; char buffer[128]; char *d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); if (value < 0) --d, *d = '-'; const int len = std::end(buffer) - d; if (os.rdbuf()->sputn(d, len) != len) os.setstate(std::ios_base::badbit); } return os; } template ostream &operator<<(ostream &os, pair a) { return os << a.first << ' ' << a.second; }; template ostream &operator<<(ostream &os, vector a) { const int n = a.size(); rep(i, n) { os << a[i]; if (i + 1 != n) os << " "; } return os; } template istream &operator>>(istream &is, pair &a) { return is >> a.first >> a.second; } template ostream &operator<<(ostream &os, array a) { rep(i, n) { os << a[i]; if (i + 1 != n) os << " "; } return os; } template istream &operator>>(istream &is, vector &a) { for (T &i : a) is >> i; return is; } template bool chmin(T &x, S y) { if ((T)y < x) { x = (T)y; return true; } return false; } template bool chmax(T &x, S y) { if (x < (T)y) { x = (T)y; return true; } return false; } template void operator++(vector &a) { for (T &i : a) ++i; } template void operator--(vector &a) { for (T &i : a) --i; } template void operator++(vector &a, int) { for (T &i : a) i++; } template void operator--(vector &a, int) { for (T &i : a) i--; } void init(), solve(); int main() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(20); cerr << fixed << setprecision(20); init(); int t = 1; cin >> t; while (t--) solve(); } // #define COMB_MAX 3e5 + 2022 // #include "lib/math/comb.hpp" // #include "lib/math/fps.hpp" #line 1 "lib/math/mint.hpp" #line 6 "lib/math/mint.hpp" #include #if defined(__GNUC__) && !defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) #pragma GCC push_options #pragma GCC optimize("O3") #endif namespace fps_detail { template constexpr bool mint_integral = std::is_integral_v #if defined(__SIZEOF_INT128__) || std::is_same_v || std::is_same_v #endif ; struct Mint { using mint = Mint; unsigned v = 0; static constexpr unsigned mod() { return 998244353; } static unsigned reduce(unsigned long long x) { return (x + (unsigned long long)(unsigned(x) * 998244351u) * mod()) >> 32; } [[gnu::always_inline]] Mint() = default; template , int> = 0> Mint(I x) { long long r = x % (long long)mod(); if (r < 0) r += mod(); v = reduce((unsigned long long)r * 932051910); } static Mint raw(unsigned x) { Mint a; a.v = reduce((unsigned long long)x * 932051910); return a; } static Mint word(unsigned x) { Mint a; a.v = x; return a; } unsigned val() const { unsigned r = reduce(v); return r < mod() ? r : r - mod(); } friend std::istream &operator>>(std::istream &is, Mint &x) { long long value; if (is >> value) x = Mint(value); return is; } friend std::ostream &operator<<(std::ostream &os, const Mint &x) { return os << x.val(); } Mint &operator+=(Mint b) { v += b.v; if (v >= 2 * mod()) v -= 2 * mod(); return *this; } Mint &operator-=(Mint b) { v -= b.v; if (v >> 31) v += 2 * mod(); return *this; } Mint &operator*=(Mint b) { v = reduce((unsigned long long)v * b.v); return *this; } Mint &operator/=(Mint b) { return *this *= b.inv(); } Mint &operator++() { return *this += Mint(1); } Mint &operator--() { return *this -= Mint(1); } Mint operator++(int) { Mint a = *this; ++*this; return a; } Mint operator--(int) { Mint a = *this; --*this; return a; } Mint operator+() const { return *this; } Mint operator-() const { return word(v ? 2 * mod() - v : 0); } Mint operator+(Mint b) const { return Mint(*this) += b; } Mint operator-(Mint b) const { return Mint(*this) -= b; } Mint operator*(Mint b) const { return Mint(*this) *= b; } Mint operator/(Mint b) const { return Mint(*this) /= b; } bool operator==(Mint b) const { return (v < mod() ? v : v - mod()) == (b.v < mod() ? b.v : b.v - mod()); } bool operator!=(Mint b) const { return !(*this == b); } template , int> = 0> friend Mint operator+(I a, Mint b) { return Mint(a) + b; } template , int> = 0> friend Mint operator-(I a, Mint b) { return Mint(a) - b; } template , int> = 0> friend Mint operator*(I a, Mint b) { return Mint(a) * b; } template , int> = 0> friend Mint operator/(I a, Mint b) { return Mint(a) / b; } template , int> = 0> friend bool operator==(I a, Mint b) { return Mint(a) == b; } template , int> = 0> friend bool operator!=(I a, Mint b) { return Mint(a) != b; } Mint pow(long long n) const { assert(n >= 0); if (!n) return Mint(1); Mint r(1), a = *this; for (; n > 1; n >>= 1, a *= a) if (n & 1) r *= a; return r * a; } [[gnu::noinline]] Mint inv() const { assert(*this != Mint(0)); Mint a2 = *this * *this, a3 = a2 * *this; Mint a7 = a3 * a3 * *this; Mint a31 = a7; for (int i = 0; i < 2; ++i) a31 *= a31; a31 *= a3; Mint r = a7; for (int i = 0; i < 3; ++i) r *= r; r *= a3; r *= r; for (int j = 0; j < 4; ++j) { for (int i = 0; i < 5; ++i) r *= r; r *= a31; } for (int i = 0; i < 3; ++i) r *= r; return r * a7; } }; } // namespace fps_detail using fps_mint = fps_detail::Mint; using mint = fps_mint; #if defined(__GNUC__) && !defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) #pragma GCC pop_options #endif #line 140 "a.cpp" void init() { // init_comb(); } #line 1 "lib/math/floor_sum/generalized_floor_sum.hpp" #line 8 "lib/math/floor_sum/generalized_floor_sum.hpp" namespace generalized_floor_sum_detail { using U = std::uint64_t; template constexpr bool integer = std::is_integral_v || std::is_same_v || std::is_same_v; template T divide(T value) { if constexpr (integer) return value / T(N); else { static const T inverse = T(1) / T(N); return value * inverse; } } template using Table = std::array, D + 1>; template struct Coefficients { std::array, D + 1> sums{}; std::array, D + 2> choose{}; std::array denominator{}, inverse{}; Coefficients() { for (int i = 0; i <= D + 1; ++i) { choose[i][0] = choose[i][i] = T(1); for (int j = 1; j < i; ++j) choose[i][j] = choose[i - 1][j - 1] + choose[i - 1][j]; } T factorial = 1; for (int p = 0; p <= D; ++p) { denominator[p] = factorial * T(p + 1); for (int k = 0; k <= p + 1; ++k) { T value = factorial * choose[p + 1][k]; for (int j = 0; j < p; ++j) if (k <= j + 1) value -= factorial / denominator[j] * choose[p + 1][j] * sums[j][k]; sums[p][k] = value; } factorial = denominator[p]; if constexpr (!integer) inverse[p] = T(1) / denominator[p]; } } T divide(T value, int p) const { if constexpr (integer) return value / denominator[p]; else return value * inverse[p]; } }; template const Coefficients &coefficients() { static const Coefficients value; return value; } template [[gnu::always_inline]] inline void translate(Table &result, const Coefficients &c, A a, B b, std::array &ak, std::array &bk) { if (a != A(0)) { ak[0] = T(1); for (int i = 1; i <= D; ++i) ak[i] = ak[i - 1] * T(a); for (int q = D; q >= 1; --q) for (int p = 0; p + q <= D; ++p) for (int j = 0; j < q; ++j) result[p][q] += c.choose[q][j] * ak[q - j] * result[p + q - j][j]; } if (b != B(0)) { bk[0] = T(1); for (int i = 1; i <= D; ++i) bk[i] = bk[i - 1] * T(b); for (int q = D; q >= 1; --q) for (int p = 0; p + q <= D; ++p) for (int j = 0; j < q; ++j) result[p][q] += c.choose[q][j] * bk[q - j] * result[p][j]; } } template Table euclidean(U n, U m, U a, U b) { Table result{}; if (!n) return result; if (n == 1) { result[0][0] = T(1); T value = T(b / m); for (int q = 1; q <= D; ++q) result[0][q] = result[0][q - 1] * value; return result; } const auto &c = coefficients(); std::array sums{}, ak{}, bk{}, kp{}; T x = T(n - 1); for (int p = 0; p <= D; ++p) { T value = c.sums[p][p + 1]; for (int j = p; j >= 0; --j) value = value * x + c.sums[p][j]; sums[p] = c.divide(value, p); } U u = a / m, v = b / m; a %= m; b %= m; if (a) { __uint128_t z = __uint128_t(a) * (n - 1) + b; U k = z >> 64 ? U(z / m) : U(z) / m; if (k) { auto child = euclidean(k, a, m, m - b - 1); kp[0] = T(1); for (int j = 1; j <= D; ++j) kp[j] = kp[j - 1] * T(k); for (int p = 0; p < D; ++p) { std::array inner{}; for (int i = 0; i < D - p; ++i) { T value = 0; for (int j = 0; j <= p + 1; ++j) value += c.sums[p][j] * child[i][j]; inner[i] = c.divide(value, p); } for (int q = 1; p + q <= D; ++q) { T value = sums[p] * kp[q]; for (int i = 0; i < q; ++i) value -= c.choose[q][i] * inner[i]; result[p][q] = value; } } } } for (int p = 0; p <= D; ++p) result[p][0] = sums[p]; translate(result, c, u, v, ak, bk); return result; } template using Signed = std::enable_if_t && std::is_integral_v && (std::is_signed_v || std::is_signed_v), int>; template bool negative(A value) { if constexpr (std::is_signed_v) return value < 0; else return false; } template std::pair normalize(A value, U m) { U x = static_cast(value); if (!negative(value)) return {x % m, T(x / m)}; x = U(0) - x; U r = x % m, q = x / m + (r != 0); if constexpr (integer) return {r ? m - r : 0, T(-__int128_t(q))}; else return {r ? m - r : 0, -T(q)}; } template auto quadratic(U n, U m, U a, U b) { std::conditional_t, std::array> result{}; if (!n) return result; T count = T(n), s1 = T(n >> 1) * T(n - 1 + (n & 1)), s2 = divide<3>(s1 * (T(2) * count - T(1))); U u = a / m, v = b / m; a %= m; b %= m; T f = 0, g = 0, h = 0; if (a) { __uint128_t z = __uint128_t(a) * (n - 1) + b; U k = z >> 64 ? U(z / m) : U(z) / m; if (k) { auto child = quadratic(k, a, m, m - b - 1); T height = T(k); f = T(n - 1) * height - child[0]; g = s1 * height - divide<2>(child[2] + child[0]); h = T(n - 1) * height * height - child[0] - T(2) * child[1]; } } T at = T(u), bt = T(v); T f0 = f + at * s1 + bt * count; T f1 = g + at * s2 + bt * s1; T f2 = h + T(2) * (at * g + bt * f) + at * at * s2 + bt * (T(2) * at * s1 + bt * count); if constexpr (Full) { result[0][0] = count; result[1][0] = s1; result[2][0] = s2; result[0][1] = f0; result[1][1] = f1; result[0][2] = f2; } else result = {f0, f1, f2}; return result; } template T linear(U n, U m, U a, U b) { T result = 0; for (;;) { if (!n) return result; if (n == 1) return result + T(b / m); if (a >= m) result += divide<2>(T(n) * T(n - 1)) * T(a / m), a %= m; if (b >= m) result += T(n) * T(b / m), b %= m; __uint128_t z = __uint128_t(a) * n + b; if (z < m) return result; if (z >> 64) n = z / m, b = z % m; else { U value = z; n = value / m; b = value % m; } std::swap(a, m); } } } template auto generalized_floor_sum_moments(std::uint64_t n, std::uint64_t m, std::uint64_t a, std::uint64_t b) { static_assert(D >= 0); assert(m > 0); if constexpr (D == 0) return generalized_floor_sum_detail::Table<0, T>{std::array{T(n)}}; else if constexpr (D == 1) { generalized_floor_sum_detail::Table<1, T> result{}; result[0][0] = T(n); result[1][0] = n ? generalized_floor_sum_detail::divide<2>(T(n) * T(n - 1)) : T(0); result[0][1] = generalized_floor_sum_detail::linear(n, m, a, b); return result; } else if constexpr (D == 2) return generalized_floor_sum_detail::quadratic(n, m, a, b); else return generalized_floor_sum_detail::euclidean(n, m, a, b); } template T generalized_floor_sum(std::uint64_t n, std::uint64_t m, std::uint64_t a, std::uint64_t b) { static_assert(P >= 0 && Q >= 0); assert(m > 0); if constexpr (Q == 0) { if (!n) return T(0); if constexpr (P == 0) return T(n); else if constexpr (P == 1) return generalized_floor_sum_detail::divide<2>(T(n) * T(n - 1)); else if constexpr (P == 2) return generalized_floor_sum_detail::divide<6>(T(n) * T(n - 1) * (T(2) * T(n) - T(1))); else { const auto &c = generalized_floor_sum_detail::coefficients(); T value = c.sums[P][P + 1], x = T(n - 1); for (int j = P; j >= 0; --j) value = value * x + c.sums[P][j]; return c.divide(value, P); } } else if constexpr (P == 0 && Q == 1) return generalized_floor_sum_detail::linear(n, m, a, b); else return generalized_floor_sum_moments

(n, m, a, b)[P][Q]; } template = 0> auto generalized_floor_sum_moments(std::uint64_t n, std::uint64_t m, A a, B b) { using namespace generalized_floor_sum_detail; static_assert(D >= 0); assert(m > 0); if (!negative(a) && !negative(b)) return generalized_floor_sum_moments(n, m, U(a), U(b)); if constexpr (D == 0) return generalized_floor_sum_moments<0, T>(n, m, U(0), U(0)); else { if (!n) return Table{}; auto [rb, v] = normalize(b, m); if (n == 1) { Table result{}; result[0][0] = T(1); for (int q = 1; q <= D; ++q) result[0][q] = result[0][q - 1] * v; return result; } auto [ra, u] = normalize(a, m); auto result = generalized_floor_sum_moments(n, m, ra, rb); std::array ak{}, bk{}; translate(result, coefficients(), u, v, ak, bk); return result; } } template = 0> T generalized_floor_sum(std::uint64_t n, std::uint64_t m, A a, B b) { using namespace generalized_floor_sum_detail; static_assert(P >= 0 && Q >= 0); assert(m > 0); if constexpr (Q == 0) return generalized_floor_sum(n, m, U(0), U(0)); else { if (!negative(a) && !negative(b)) return generalized_floor_sum(n, m, U(a), U(b)); return generalized_floor_sum_moments

(n, m, a, b)[P][Q]; } } #line 144 "a.cpp" void solve() { long p, q, n, m, a, b; cin >> p >> q >> n >> m >> a >> b; cout << generalized_floor_sum_moments<21, mint>(n + 1, m, a, b)[p][q] << endl; }