#include using namespace std; #include using namespace atcoder; #define int long long // #define endl "\n" #pragma GCC optimize("-O3") void solve(); typedef long long ll; typedef __int128_t LL; typedef unsigned long long ull; typedef double db; typedef long double ld; typedef pair pi; typedef pair> pip; typedef vector vi; typedef vector vd; typedef vector vb; typedef vector vs; typedef vector vc; typedef vector> vp; typedef vector> vvi; typedef vector> vvd; typedef vector> vvb; typedef vector> vvs; typedef vector> vvc; typedef vector>> vvp; typedef vector>> vvvi; typedef vector>>> vvvvi; template using vec = vector; template using vv = vector>; template using vvv = vector>>; template using vvvv = vector>>>; template using pq = priority_queue; template using pqg = priority_queue, greater>; template using mset = multiset; template using uset = unordered_set; template using umap = unordered_map; #define _PI 3.14159265358979323846 #define _E 2.7182818284590452354 #define fi first #define se second #define pb push_back #define eb emplace_back #define mp make_pair #define mt make_tuple #define td typedef #define elif else if #define ifnot(x) if(!(x)) #define all(obj) (obj).begin(), (obj).end() #define rall(obj) (obj).rbegin(), (obj).rend() #define sumv(a) accumulate(all(a), 0LL) #define lb(v, a) (lower_bound(begin(v), end(v), a) - begin(v)) #define ub(v, a) (upper_bound(begin(v), end(v), a) - begin(v)) #define inr(l, x, r) (l <= x && x < r) #define cbit(x) __builtin_popcountll(x) #define topbit(t) (t == 0 ? -1 : 63 - __builtin_clzll(t)) #define botbit(t) (t == 0 ? 64 : __builtin_ctzll(t)) #define gbit(msk, i) ((msk) >> (i) & 1) #define mask(x) ((1LL << (x)) - 1) #define setbits(i, n) \ for(int j = (n), i = botbit(j); j; j ^= 1LL << i, i = botbit(j)) #define rep1(a) \ for(int NEVER_USE_VARIABLE = 0; NEVER_USE_VARIABLE < (int)a; \ NEVER_USE_VARIABLE++) #define rep2(i, a) for(int i = 0; i < (int)a; i++) #define rep3(i, a, b) for(int i = a; i < (int)b; i++) #define rep4(i, a, b, c) for(int i = a; i < (int)b; i += c) #define overload4(a, b, c, d, e, ...) e #define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__) #define rrep1(n) for(ll NEVER_USE_VARIABLE = n; NEVER_USE_VARIABLE--;) #define rrep2(i, n) for(ll i = n; i--;) #define rrep3(i, a, b) for(ll i = b; i-- > (a);) #define rrep4(i, a, b, c) \ for(ll i = (a) + ((b) - (a)-1) / (c) * (c); i >= (a); i -= c) #define rrep(...) \ overload4(__VA_ARGS__, rrep4, rrep3, rrep2, rrep1)(__VA_ARGS__) #define fore1(i, a) for(auto &&i : a) #define fore2(x, y, a) for(auto &&[x, y] : a) #define fore3(x, y, z, a) for(auto &&[x, y, z] : a) #define fore(...) overload4(__VA_ARGS__, fore3, fore2, fore1)(__VA_ARGS__) #define ryes return yes(); #define rno return no(); #define rerr return err(); istream &operator>>(istream &is, modint998244353 &a) { long long v; is >> v; a = v; return is; } ostream &operator<<(ostream &os, const modint998244353 &a) { return os << a.val(); } istream &operator>>(istream &is, modint1000000007 &a) { long long v; is >> v; a = v; return is; } ostream &operator<<(ostream &os, const modint1000000007 &a) { return os << a.val(); } template istream &operator>>(istream &is, pair &p) { is >> p.first >> p.second; return is; } template ostream &operator<<(ostream &os, const pair &p) { os << p.first << "," << p.second; return os; } template ostream &operator<<(ostream &s, set P) { fore(it, P) { s << it << " "; } return s; } template ostream &operator<<(ostream &s, map P) { fore(x, y, P) { s << "<" << x << "->" << y << "> "; } return s; } template ostream &operator<<(ostream &s, multiset P) { fore(it, P) { s << it << " "; } return s; } template ostream &operator<<(ostream &s, unordered_set P) { fore(it, P) { s << it << " "; } return s; } template ostream &operator<<(ostream &s, unordered_map P) { fore(x, y, P) { s << "<" << x << "->" << y << "> "; } return s; } template istream &operator>>(istream &is, vector &v) { for(auto &e : v) is >> e; return is; } template ostream &operator<<(ostream &os, const vector &v) { for(auto &e : v) os << e << ' '; return os; } template ostream &operator<<(ostream &os, const vector> &v) { for(auto &e : v) { for(auto &c : e) os << c << ' '; os << endl; } return os; } template vector &operator++(vector &v) { for(auto &e : v) e++; return v; } template vector operator++(vector &v, signed) { auto res = v; for(auto &e : v) e++; return res; } template vector &operator--(vector &v) { for(auto &e : v) e--; return v; } template vector operator--(vector &v, signed) { auto res = v; for(auto &e : v) e--; return res; } // 十進数からb進数へ template string to_baseB(T x, int b = 10) { string ans; do { int num = x % b; ans = (char)((num <= 9) ? ('0' + num) : ('A' + num - 10)) + ans; x /= b; } while(x != 0); return ans; } // b進数から十進数へ long long to_base10(const string &x, int b = 10) { long long ans = 0, base = 1; for(int i = x.length() - 1; i >= 0; --i) { int num = ('0' <= x[i] && x[i] <= '9') ? (x[i] - '0') : (x[i] - 'A' + 10); ans += base * num; base *= b; } return ans; } ostream &operator<<(ostream &s, const LL &p) { s << to_baseB(p); return s; } // debug methods // usage: debug(x,y); #define CHOOSE(a) CHOOSE2 a #define CHOOSE2(a0, a1, a2, a3, a4, x, ...) x #define debug_1(x1) cout << #x1 << ": " << x1 << endl #define debug_2(x1, x2) \ cout << #x1 << ": " << x1 << ", " #x2 << ": " << x2 << endl #define debug_3(x1, x2, x3) \ cout << #x1 << ": " << x1 << ", " #x2 << ": " << x2 << ", " #x3 << ": " \ << x3 << endl #define debug_4(x1, x2, x3, x4) \ cout << #x1 << ": " << x1 << ", " #x2 << ": " << x2 << ", " #x3 << ": " \ << x3 << ", " #x4 << ": " << x4 << endl #define debug_5(x1, x2, x3, x4, x5) \ cout << #x1 << ": " << x1 << ", " #x2 << ": " << x2 << ", " #x3 << ": " \ << x3 << ", " #x4 << ": " << x4 << ", " #x5 << ": " << x5 << endl #ifdef _DEBUG #define debug(...) \ CHOOSE((__VA_ARGS__, debug_5, debug_4, debug_3, debug_2, debug_1, ~)) \ (__VA_ARGS__) #else #define debug(...) #endif void out() { cout << endl; } template void out(const T &a) { cout << a; cout << endl; } template void out(const T &a, const Ts &...b) { cout << a; (cout << ... << (cout << ' ', b)); cout << endl; } #define rout_1(x1) return out(x1) #define rout_2(x1, x2) return out(x1, x2) #define rout_3(x1, x2, x3) return out(x1, x2, x3) #define rout_4(x1, x2, x3, x4) return out(x1, x2, x3, x4) #define rout_5(x1, x2, x3, x4, x5) return out(x1, x2, x3, x4, x5) #define rout(...) \ CHOOSE((__VA_ARGS__, rout_5, rout_4, rout_3, rout_2, rout_1, ~)) \ (__VA_ARGS__) struct fast_ios { fast_ios() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(12); }; } fast_ios_; struct Binomial { int p; int MAX; vector fac, finv, inv; // テーブルを作る前処理 Binomial(int p_, int n = 1) : p(p_), MAX(1), fac(2), finv(2), inv(2) { fac[0] = fac[1] = 1; finv[0] = finv[1] = 1; inv[1] = 1; if(n != 1) build(n); } void build(int new_max) { MAX++; fac.resize(new_max + 1); inv.resize(new_max + 1); finv.resize(new_max + 1); for(; MAX <= new_max; MAX++) { fac[MAX] = fac[MAX - 1] * MAX % p; inv[MAX] = p - inv[p % MAX] * (p / MAX) % p; finv[MAX] = finv[MAX - 1] * inv[MAX] % p; } MAX--; } // nCk long long mod_comb(int n, int k) { if(n < k) return 0; if(n < 0 || k < 0) return 0; if(n > MAX) build(n); return fac[n] * (finv[k] * finv[n - k] % p) % p; } long long operator()(int n, int k) { return mod_comb(n, k); } // nPk long long mod_perm(int n, int k) { if(n < k) return 0; if(n < 0 || k < 0) return 0; if(n > MAX) build(n); return fac[n] * finv[n - k] % p; } // n! long long operator[](int n) { if(n > MAX) build(n); return fac[n]; } // 1/n! long long operator()(int n) { if(n > MAX) build(n); return finv[n]; } }; template struct modpow { long long x, m; int n; vector d; modpow(long long x) : x(x), n(1), d(1, 1) {} T operator[](int i) { while(n <= i) d.push_back(d.back() * x), ++n; return d[i]; } }; modpow two(2), ten(10); struct RandomNumberGenerator { mt19937 mt; RandomNumberGenerator() : mt(chrono::steady_clock::now().time_since_epoch().count()) {} long long operator()(long long a, long long b) { // [a, b) uniform_int_distribution dist(a, b - 1); return dist(mt); } long long operator()(long long b) { // [0, b) return (*this)(0, b); } long long operator()() { return (*this)(0, 1LL << 60); } double operator[](double a) { return (double)(*this)(0, 1LL << 60) / (1LL << 60) * a; } double normal_dist(double sigma, double mean = 0) { std::normal_distribution<> dist(mean, sigma); return dist(mt); } } rnd; clock_t start_time = clock(); double now_time() { clock_t end_time = clock(); return (double)(end_time - start_time) / CLOCKS_PER_SEC; } void input_graph(vector> &g, int m = -1, int bidirected = true) { if(m == -1) m = g.size() - 1; for(int i = 0; i < m; i++) { int u, v; cin >> u >> v; u--; v--; g[u].push_back(v); if(bidirected) g[v].push_back(u); } } vector iota(int n, int s = 0) { vi a(n); iota(a.begin(), a.end(), s); return a; } template void sort(vector &v) { sort(all(v)); } template void rsort(vector &v) { sort(rall(v)); } template void reverse(T &v) { reverse(all(v)); } template auto max(const T &a) { return *max_element(a.begin(), a.end()); } template auto min(const T &a) { return *min_element(a.begin(), a.end()); } template int max_id(const T &a) { return max_element(a.begin(), a.end()) - a.begin(); } template int min_id(const T &a) { return min_element(a.begin(), a.end()) - a.begin(); } long long max(signed x, long long y) { return max((long long)x, y); } long long max(long long x, signed y) { return max(x, (long long)y); } long long min(signed x, long long y) { return min((long long)x, y); } long long min(long long x, signed y) { return min(x, (long long)y); } template bool chmax(T &a, const S &b) { if(a < (T)b) { a = (T)b; return 1; } return 0; } template bool chmin(T &a, const S &b) { if((T)b < a) { a = (T)b; return 1; } return 0; } template vector uniq(vector v) { sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); return v; } template vector compress(vector v) { vector v2(v.size()); v2 = v; sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); for(int i = 0; i < (int)v2.size(); i++) { v2[i] = lower_bound(v.begin(), v.end(), v2[i]) - v.begin(); } return v2; } vector inverse(vector &p) { int n = p.size(); vector inv(n); for(int i = 0; i < n; i++) inv[p[i]] = i; return inv; } template vector> idx_pair(vector &a) { int n = a.size(); vector> res(n); for(int i = 0; i < n; i++) res[i] = {a[i], i}; return res; } template vector acc0(vector &v) { vector res(v.size()); if((int)v.size() == 0) return res; res[0] = v[0]; for(int i = 1; i < (int)v.size(); i++) { res[i] = res[i - 1] + v[i]; } return res; } template vector acc1(vector &v) { vector res(v.size() + 1); for(int i = 0; i < (int)v.size(); i++) { res[i + 1] = res[i] + v[i]; } return res; } template vector> acc0(vector> v) { int h = v.size(), w = v[0].size(); for(int i = 0; i < h; i++) { for(int j = 1; j < w; j++) { v[i][j] += v[i][j - 1]; } } for(int i = 1; i < h; i++) { for(int j = 0; j < w; j++) { v[i][j] += v[i - 1][j]; } } return v; } template vector> acc1(vector> &v) { int h = v.size(), w = v[0].size(); vector> res(h + 1, vector(w + 1)); for(int i = 0; i < h; i++) { for(int j = 0; j < w; j++) { res[i + 1][j + 1] = v[i][j] + res[i + 1][j]; } } for(int i = 0; i < h; i++) { for(int j = 0; j < w; j++) { res[i + 1][j + 1] += res[i][j + 1]; } } return res; } template void erase1(multiset &st, int x) { auto it = st.find(x); assert(it != st.end()); st.erase(it); } long long exp(long long x, int n) { long long res = 1; while(n > 0) { if(n & 1) res = res * x; x = x * x; n >>= 1; } return res; } int countDigits(long long n) { string tmp = to_string(n); return (int)tmp.size(); } long long sq(long long n) { return n * n; } long long ceil(long long x, long long y) { return (x + y - 1) / y; } long long floor(long long x, long long y) { return (y < 0 ? floor(-x, -y) : (x > 0 ? x / y : x / y - (x % y == 0 ? 0 : 1))); } constexpr long long tri(long long n) { return n * (n + 1) / 2; } // l + ... + r constexpr long long tri(long long l, long long r) { return (l + r) * (r - l + 1) / 2; } int ctoi(const char &c, const char start = '0') { return c - start; } int atoi(const char &c, const char start = 'a') { return c - start; } vector ctoi(string &s, const char start = '0') { vector res; for(auto &c : s) { int x = c - start; if(x < 0 || x >= 10) x = -1; res.push_back(x); } return res; } vector atoi(string &s, const char start = 'a') { vector res; for(auto &c : s) { int x = c - start; if(x < 0 || x >= 26) x = -1; res.push_back(x); } return res; } int mex(vector &a) { int n = a.size(); vector cnt(n + 1); for(int i = 0; i < n; i++) { if(a[i] > n) continue; cnt[a[i]]++; } int res = 0; while(cnt[res]) res++; return res; } void yes() { cout << "Yes" << endl; } void no() { cout << "No" << endl; } void yesno(bool x) { if(x) yes(); else no(); } void err() { cout << -1 << endl; } int dx[] = {1, 0, -1, 0, 1, 1, -1, -1}; int dy[] = {0, 1, 0, -1, -1, 1, 1, -1}; long long inf = (1 << 30) + (1LL << 60) - 2; double eps = 1e-9; // long long mod = 67280421310721; // using mint = static_modint<1000000009>; // using mint = dynamic_modint<1000000009>; // long long mod = 1000000007; // using mint = modint1000000007; long long mod = 998244353; using mint = modint998244353; typedef vector vm; typedef vector> vvm; typedef vector>> vvvm; // Binomial C(mod); // modpow mtwo(2), mten(10); //////////////////////////////////////////////////////////////////////////////////////////// /* 蟻本p256を参考に https://ei1333.github.io/luzhiled/snippets/math/matrix.html を参考に https://atcoder.jp/contests/abc253/submissions/32166405 を参考に(det) Matrix(int h,int w,T val=0):縦h,横w,中身valで初期化 unit:単位行列 演算:+,+=,-,-=,*,*=,==,[][] (*はMarix,vector,Tに対し、それぞれ定義してある) (*vectorは、転置した縦ベクトルをかけた縦ベクトルを返していることに注意) T det():行列式 Matrix Inv():逆行列。存在しない場合はMatrix()が返る。 vector gauss_jordan(vector B): Ax=bとなるx。Aの逆行列が存在しない場合、空の配列を返す。 coutで出力可 */ template struct Matrix { int h, w; vector> d; Matrix() : h(0), w(0) {} Matrix(int h, int w) : h(h), w(w), d(h, vector(w)) {} Matrix(int n) : h(n), w(n), d(n, vector(n)) {} Matrix &unit() { assert(h == w); rep(i, h) d[i][i] = 1; return *this; } const vector &operator[](int i) const { return d[i]; } vector &operator[](int i) { return d[i]; } Matrix operator+(const Matrix &a) const { assert(w == a.h); Matrix r(h, a.w); for(int i = 0; i < h; i++) for(int j = 0; j < w; j++) { r[i][j] = d[i][j] + a[i][j]; } return r; } Matrix &operator+=(const Matrix &B) { for(int i = 0; i < h; i++) { for(int j = 0; j < w; j++) { (*this)[i][j] += B[i][j]; } } return *this; } Matrix operator-(const Matrix &a) const { assert(w == a.h); Matrix r(h, a.w); for(int i = 0; i < h; i++) for(int j = 0; j < w; j++) { r[i][j] = d[i][j] - a[i][j]; } return r; } Matrix &operator-=(const Matrix &B) { for(int i = 0; i < h; i++) { for(int j = 0; j < w; j++) { (*this)[i][j] -= B[i][j]; } } return *this; } Matrix operator*(const Matrix &a) const { assert(w == a.h); Matrix r(h, a.w); for(int i = 0; i < h; i++) { for(int k = 0; k < w; k++) { for(int j = 0; j < a.w; j++) { r[i][j] += d[i][k] * a[k][j]; } } } return r; } Matrix &operator*=(const Matrix &a) { assert(w == a.h); vector> r(h, vector(w)); for(int i = 0; i < h; i++) { for(int k = 0; k < w; k++) { for(int j = 0; j < a.w; j++) { r[i][j] += (*this)[i][k] * a[k][j]; } } } d.swap(r); return (*this); } vector operator*(const vector &B) const { vector C(h); assert((int)B.size() == w); for(int i = 0; i < h; i++) { for(int j = 0; j < w; j++) { C[i] += (*this)[i][j] * B[j]; } } return C; } Matrix operator*(const T &x) const { Matrix C(h, w); for(int i = 0; i < h; i++) { for(int j = 0; j < w; j++) { C[i][j] += (*this)[i][j] * x; } } return C; } Matrix &operator*=(const T &x) { vector> r(h, vector(w)); for(int i = 0; i < h; i++) for(int j = 0; j < w; j++) { r[i][j] += (*this)[i][j] * x; } d.swap(r); return (*this); } bool operator==(const Matrix &b) { if(h != b.h) return false; if(w != b.w) return false; for(int i = 0; i < h; i++) { for(int j = 0; j < w; j++) { if((*this)[i][j] != b[i][j]) return false; } } return true; } T det() { assert(h == w); T res = 1; rep(k, h) { for(int i = k; i < h; ++i) { if(d[i][k] == 0) continue; if(i != k) { swap(d[i], d[k]); res = -res; } } if(d[k][k] == 0) return 0; res *= d[k][k]; T inv = T(1) / d[k][k]; for(int j = 0; j < h; j++) d[k][j] *= inv; for(int i = k + 1; i < h; ++i) { T c = d[i][k]; for(int j = k; j < h; ++j) d[i][j] -= d[k][j] * c; } } return res; } Matrix pow(long long t) const { assert(h == w); if(!t) return Matrix(h, h).unit(); if(t == 1) return *this; Matrix r = pow(t >> 1); r = r * r; if(t & 1) r = r * (*this); return r; } // 逆行列を返す。ガウスの消去法。存在しない場合は長さ0の配列を返す。 Matrix Inv() { assert(h == w); int n = h; Matrix B(n, 2 * n); for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { B[i][j] = d[i][j]; } B[i][i + n] = 1; } for(int i = 0; i < n; i++) { // 注目している変数の係数の絶対値が大きい式をi番目に持ってくる int pivot = i; for(int j = i; j < n; j++) { if(B[j][i] != 0) { pivot = j; break; } } swap(B[i], B[pivot]); // 逆行列存在しない if(B[i][i] == 0) return Matrix(); for(int j = i + 1; j < 2 * n; j++) B[i][j] /= B[i][i]; for(int j = 0; j < n; j++) { if(i != j) { for(int k = i + 1; k < 2 * n; k++) B[j][k] -= B[j][i] * B[i][k]; } } } Matrix res(n, n); for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) res[i][j] = B[i][j + n]; } return res; } // Ax=bとなるx。Aの逆行列が存在しない場合、空の配列を返す。 vector gauss_jordan(vector b) { Matrix inv = (*this).Inv(); if(inv.h == 0) return {}; b = inv * b; return b; } friend ostream &operator<<(ostream &os, Matrix &p) { for(int i = 0; i < p.h; i++) { for(int j = 0; j < p.w; j++) { os << p[i][j] << " "; } os << endl; } return (os); } }; //////////////////////////////////////////////////////////////////////////////////////////// signed main() { int testcase = 1; cin >> testcase; for(int i = 0; i < testcase; i++) { solve(); } } void solve() { int n, m; cin >> n >> m; // swap(n, m); Matrix mat(3); mat[0][0] = 1; mat[0][1] = 1; mat[0][2] = 1; mat[1][0] = n; mat[1][1] = n - 1; mat[1][2] = n - 2; mat[2][0] = n * (n - 3) / 2; mat[2][1] = (n - 3) * (n - 2) / 2; mat[2][2] = ((n >= 5) ? (n - 2) * (n - 5) / 2 : 0) + ((n < 3) ? 2 : ((n == 4) ? 1 : 2)); vm x = {1, 0, 0}; // debug(mat); auto res = mat.pow(m) * x; out(res[0] + res[1] + res[2]); }