#include // assert #include // cin, cout, ios #include // swap, pair using ll = long long; using lll = __int128_t; std::istream& operator>>(std::istream& is, lll& v) { ll x; is >> x; v = lll(x); return is; } std::ostream& operator<<(std::ostream& os, const lll v) { std::ostream::sentry s(os); if (s) { __uint128_t tmp = v < 0 ? -v : v; char buffer[40]; // 128bit 十進数は最大39桁 char* d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); if (v < 0) { --d; *d = '-'; } os.write(d, std::end(buffer) - d); } return os; } template bool chmax(T& a, T b){if(a < b){a = b; return true;} return false;} template constexpr std::pair divmod(T a, T b) { T q = a / b; T r = a % b; return {q, r}; } // 商を無限大方向に切り下げる除算(剰余が0でない時の符号は除数の符号に一致) template constexpr std::pair divmod_floor(T a, T b) { // 標準の truncating 除算を使う T q = a / b; T r = a % b; // もし符号が食い違っていたら 1 調整 if ((r != 0) && ((r > 0) != (b > 0))) { q -= 1; r += b; } return {q, r}; } // 剰余が非負になる除算(ユークリッド除算) template constexpr std::pair divmod_euclid(T a, T b) { // 標準の truncating 除算を使う T q = a / b; T r = a % b; // 剰余が負なら 1 調整 if (r < 0) { if (b > 0) { q -= 1; r += b; } else { q += 1; r -= b; } } return {q, r}; } /** Max Weighted Floor (mwf) の非再帰実装。 mwf(n,m,a,b,c,d) = max_{0 <= x < n} a*x + b*floor((c*x + d)/m) 前提: - l < r, 0 < m 計算量/メモリ: - 時間: O(log m)(ユークリッド互除法的再帰による構造縮約) - 追加メモリ: O(1) */ template T mwf(T l, T r, T m, T a, T b, T c, T d) { assert(l < r && 0 < m); T n = r - l; const auto [qc0, rc0] = divmod_euclid(c, m); c = rc0; a += b * qc0; const auto [qd0, rd0] = divmod_euclid(c * l + d, m); d = rd0; T sum_acc = a * l + b * qd0; T max_acc = sum_acc; while(true) { assert(0 < n && 0 < m && 0 <= c && c < m && 0 <= d && d < m); // 0 ≤ x < n における y = floor((c*x+d)/m) の最大値 y_max を計算 const T y_max = (c * (n - 1) + d) / m; // y_max >= 0 // 現在の小問題における x = 0, n-1 のときの値を max_acc に反映 chmax(max_acc, sum_acc); chmax(max_acc, sum_acc + a * (n - 1) + b * y_max); // x = 0, n-1 のいずれかで最大値を取るのが確定したら終了 if(y_max == 0 || (a >= 0 && b >= 0) || (a <= 0 && b <= 0)) { return max_acc; } // 小問題へのパラメータ変換 if(a < 0) { sum_acc += a + b; } n = y_max; d = m - d - 1; std::swap(a, b); std::swap(c, m); assert(0 < n && 0 < m && 0 < c && 0 <= d); // 2回目以降の正規化: c,d を m で割った余りに変換し、a,b,sum_acc を更新 // c,d,m は非負なので通常の剰余で良い const auto [qc1, rc1] = divmod(c, m); c = rc1; a += b * qc1; const auto [qd1, rd1] = divmod(d, m); d = rd1; sum_acc += b * qd1; } } int main() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); int t; lll n, m, a, b, c, d, ans; std::cin >> t; for(int i = 0; i < t; i++) { std::cin >> n >> m >> a >> b >> c >> d; assert(n > 0 && m > 0); ans = mwf(0, n, m, a, b, c, d); std::cout << ans << '\n'; } }