結果
問題 | No.2529 Treasure Hunter |
ユーザー |
![]() |
提出日時 | 2023-11-03 23:37:06 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 50 ms / 2,000 ms |
コード長 | 28,259 bytes |
コンパイル時間 | 2,434 ms |
コンパイル使用メモリ | 206,924 KB |
最終ジャッジ日時 | 2025-02-17 18:58:22 |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 22 |
ソースコード
#line 1 "playspace/main.cpp"#include <bits/stdc++.h>#line 3 "library/gandalfr/math/matrix.hpp"#line 8 "library/gandalfr/math/matrix.hpp"template <class T> class matrix {private:int H, W;std::valarray<std::valarray<T>> table;enum rowtrans_operation_name { SCALE, SWAP, ADD };struct rowtrans_operation {int op, tar, res;T scl;};using operations_history = std::vector<rowtrans_operation>;public:matrix() = default;matrix(int _H, int _W, T val = 0): H(_H), W(_W), table(std::valarray<T>(val, _W), _H) {}matrix(const std::vector<std::vector<T>> &vv): H(vv.size()), W(vv[0].size()), table(std::valarray<T>(W), H) {for (int i = 0; i < H; i++)for (int j = 0; j < W; j++)table[i][j] = vv[i][j];}matrix(const std::valarray<std::valarray<T>> &vv): H(vv.size()), W(vv[0].size()), table(vv) {}/*** @brief 行列をリサイズする。* @param val 拡張部分の値*/void resize(int _H, int _W, T val = 0) {H = _H, W = _W;table.resize(_H, std::valarray<T>(val, _H));}int size_H() const { return H; }int size_W() const { return W; }void transpose() {matrix<T> ret(W, H);for (int i = 0; i < H; i++)for (int j = 0; j < W; j++)ret.table[j][i] = table[i][j];*this = ret;}/*** @brief 第 i 行に対して行単位で代入を行う* @example A.row_assign(3, {1,2,3});*/void row_assign(int i, const std::valarray<T> &row) {assert(0 <= i && i < H);assert(W == (int)row.size());table[i] = row;}/*** @brief 第 i 行, 第 j 行を入れ替える*/void row_swap(int i, int j) {assert(0 <= i && i < H);assert(0 <= j && j < H);table[i].swap(table[j]);}/*** @attention O(n^3)* @attention 整数型では正しく計算できない。double や fraction を使うこと。* @attention 枢軸選びをしていないので double では誤差が出るかも。*/operations_history sweep_method() {operations_history hist;for (int h = 0, w = 0; h < H && w < W; w++) {if (table[h][w] == 0) {for (int piv = h + 1; piv < H; piv++) {if (table[piv][w] != 0) {hist.push_back({SWAP, h, piv, 0});row_swap(h, piv);break;}}if (table[h][w] == 0) {continue;}}T inv = 1 / table[h][w];hist.push_back({SCALE, -1, w, inv});table[h] *= inv;for (int j = h + 1; j < H; j++) {hist.push_back({ADD, h, j, -table[j][w]});table[j] -= table[h] * table[j][w];}h++;}return hist;}int rank() const {auto U(*this);U.sweep_method();int r = 0;for (int i = 0; i < H; ++i) {for (int j = i; j < W; ++j) {if (U.table[i][j] != 0) {r++;break;}}}return r;}T determinant() const {assert(H == W);matrix<T> U(*this);T det = 1;auto hist = U.sweep_method();if (U.table[H - 1][H - 1] == 0)return 0;for (auto &[op, tar, res, scl] : hist) {switch (op) {case SCALE:det /= scl;break;case SWAP:det *= -1;break;}}return det;}std::vector<T> solve_system_of_equations(const std::vector<T> &y) {assert(H == W);std::vector<T> x(y);matrix<T> U(*this);auto hist = U.sweep_method();if (U.table[H - 1][H - 1] == 0)return {};for (auto &[op, tar, res, scl] : hist) {switch (op) {case SCALE:x[res] *= scl;break;case SWAP:std::swap(x[tar], x[res]);break;case ADD:x[res] += x[tar] * scl;break;}}for (int i = H - 1; i >= 0; --i) {for (int j = 0; j < i; ++j) {x[j] -= U.table[j][i] * x[i];}}return x;}matrix<T> inverse() const {assert(H == W);matrix<T> INV(matrix<T>::E(H)), U(*this);auto hist = U.sweep_method();if (U.table[H - 1][H - 1] == 0)return matrix<T>(0, 0);for (auto &[op, tar, res, scl] : hist) {switch (op) {case SCALE:INV.table[res] *= scl;break;case SWAP:std::swap(INV.table[tar], INV.table[res]);break;case ADD:INV.table[res] += INV.table[tar] * scl;break;}}for (int i = H - 1; i >= 0; --i) {for (int j = 0; j < i; ++j) {INV.table[j] -= INV.table[i] * U.table[j][i];}}return INV;}void print() const {for (int i = 0; i < H; i++) {for (int j = 0; j < W; j++) {std::cout << table[i][j] << (j == W - 1 ? "" : " ");}std::cout << std::endl;}}matrix<T> &operator+=(const matrix<T> &a) {this->table += a.table;return *this;}matrix<T> &operator-=(const matrix<T> &a) {this->table -= a.table;return *this;}matrix<T> &operator*=(const T &a) {this->table *= a;return *this;}matrix<T> &operator*=(const matrix<T> &a) {assert(W == a.H);matrix<T> a_t(a), ret(H, a.W);a_t.transpose();for (int i = 0; i < H; i++) {for (int j = 0; j < a_t.H; j++) {ret.table[i][j] = (table[i] * a_t.table[j]).sum();}}return *this = ret;}matrix<T> &operator/=(const T &a) {this->table /= a;return *this;}/*** @brief 行列の冪乗。* @param n 指数* @attention n が 0 なら単位行列。* @attention 演算子の優先度に注意。*/matrix<T> operator^=(long long n) {assert(H == W);if (n == 0)return *this = E(H);n--;matrix<T> x(*this);while (n) {if (n & 1)*this *= x;x *= x;n >>= 1;}return *this;}matrix<T> operator+() const { return *this; }matrix<T> operator-() const { return matrix<T>(*this) *= -1; }matrix<T> operator+(const matrix<T> &a) const {return matrix<T>(*this) += a;}matrix<T> operator-(const matrix<T> &a) const {return matrix<T>(*this) -= a;}matrix<T> operator*(const T &a) { return matrix<T>(*this) *= a; }matrix<T> operator*(const matrix<T> &a) const {return matrix<T>(*this) *= a;}matrix<T> operator/(const T &a) const { return matrix<T>(*this) /= a; }matrix<T> operator^(long long n) const { return matrix<T>(*this) ^= n; }friend std::istream &operator>>(std::istream &is, matrix<T> &mt) {for (auto &arr : mt.table)for (auto &x : arr)is >> x;return is;}const T &operator()(int h, int w) const {assert(0 <= h && h < H && 0 <= w && w <= W);return table[h][w];}T &operator()(int h, int w) {assert(0 <= h && h < H && 0 <= w && w <= W);return table[h][w];}template <typename S> bool operator==(const matrix<S> &other) {if (size_H() != other.size_H() || size_W() != other.size_W())return false;for (int h = 0; h < H; ++h) {for (int w = 0; w < W; ++w) {if (table[h][w] != other.table[h][w])return false;}}return true;}template <typename S> bool operator!=(const matrix<S> &other) {return !operator==(other);}/*** @brief サイズ n の単位行列。*/static matrix<T> E(int N) {matrix<T> ret(N, N);for (int i = 0; i < N; i++)ret.table[i][i] = 1;return ret;}};#line 8 "library/gandalfr/other/io_supporter.hpp"#line 1 "library/atcoder/modint.hpp"#line 6 "library/atcoder/modint.hpp"#include <type_traits>#ifdef _MSC_VER#include <intrin.h>#endif#line 1 "library/atcoder/internal_math.hpp"#line 5 "library/atcoder/internal_math.hpp"#ifdef _MSC_VER#include <intrin.h>#endifnamespace atcoder {namespace internal {// @param m `1 <= m`// @return x mod mconstexpr long long safe_mod(long long x, long long m) {x %= m;if (x < 0) x += m;return x;}// Fast modular multiplication by barrett reduction// Reference: https://en.wikipedia.org/wiki/Barrett_reduction// NOTE: reconsider after Ice Lakestruct barrett {unsigned int _m;unsigned long long im;// @param m `1 <= m < 2^31`explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}// @return munsigned int umod() const { return _m; }// @param a `0 <= a < m`// @param b `0 <= b < m`// @return `a * b % m`unsigned int mul(unsigned int a, unsigned int b) const {// [1] m = 1// a = b = im = 0, so okay// [2] m >= 2// im = ceil(2^64 / m)// -> im * m = 2^64 + r (0 <= r < m)// let z = a*b = c*m + d (0 <= c, d < m)// a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im// c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2// ((ab * im) >> 64) == c or c + 1unsigned long long z = a;z *= b;#ifdef _MSC_VERunsigned long long x;_umul128(z, im, &x);#elseunsigned long long x =(unsigned long long)(((unsigned __int128)(z)*im) >> 64);#endifunsigned int v = (unsigned int)(z - x * _m);if (_m <= v) v += _m;return v;}};// @param n `0 <= n`// @param m `1 <= m`// @return `(x ** n) % m`constexpr long long pow_mod_constexpr(long long x, long long n, int m) {if (m == 1) return 0;unsigned int _m = (unsigned int)(m);unsigned long long r = 1;unsigned long long y = safe_mod(x, m);while (n) {if (n & 1) r = (r * y) % _m;y = (y * y) % _m;n >>= 1;}return r;}// Reference:// M. Forisek and J. Jancina,// Fast Primality Testing for Integers That Fit into a Machine Word// @param n `0 <= n`constexpr bool is_prime_constexpr(int n) {if (n <= 1) return false;if (n == 2 || n == 7 || n == 61) return true;if (n % 2 == 0) return false;long long d = n - 1;while (d % 2 == 0) d /= 2;constexpr long long bases[3] = {2, 7, 61};for (long long a : bases) {long long t = d;long long y = pow_mod_constexpr(a, t, n);while (t != n - 1 && y != 1 && y != n - 1) {y = y * y % n;t <<= 1;}if (y != n - 1 && t % 2 == 0) {return false;}}return true;}template <int n> constexpr bool is_prime = is_prime_constexpr(n);// @param b `1 <= b`// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/gconstexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {a = safe_mod(a, b);if (a == 0) return {b, 0};// Contracts:// [1] s - m0 * a = 0 (mod b)// [2] t - m1 * a = 0 (mod b)// [3] s * |m1| + t * |m0| <= blong long s = b, t = a;long long m0 = 0, m1 = 1;while (t) {long long u = s / t;s -= t * u;m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b// [3]:// (s - t * u) * |m1| + t * |m0 - m1 * u|// <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)// = s * |m1| + t * |m0| <= bauto tmp = s;s = t;t = tmp;tmp = m0;m0 = m1;m1 = tmp;}// by [3]: |m0| <= b/g// by g != b: |m0| < b/gif (m0 < 0) m0 += b / s;return {s, m0};}// Compile time primitive root// @param m must be prime// @return primitive root (and minimum in now)constexpr int primitive_root_constexpr(int m) {if (m == 2) return 1;if (m == 167772161) return 3;if (m == 469762049) return 3;if (m == 754974721) return 11;if (m == 998244353) return 3;int divs[20] = {};divs[0] = 2;int cnt = 1;int x = (m - 1) / 2;while (x % 2 == 0) x /= 2;for (int i = 3; (long long)(i)*i <= x; i += 2) {if (x % i == 0) {divs[cnt++] = i;while (x % i == 0) {x /= i;}}}if (x > 1) {divs[cnt++] = x;}for (int g = 2;; g++) {bool ok = true;for (int i = 0; i < cnt; i++) {if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {ok = false;break;}}if (ok) return g;}}template <int m> constexpr int primitive_root = primitive_root_constexpr(m);// @param n `n < 2^32`// @param m `1 <= m < 2^32`// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)unsigned long long floor_sum_unsigned(unsigned long long n,unsigned long long m,unsigned long long a,unsigned long long b) {unsigned long long ans = 0;while (true) {if (a >= m) {ans += n * (n - 1) / 2 * (a / m);a %= m;}if (b >= m) {ans += n * (b / m);b %= m;}unsigned long long y_max = a * n + b;if (y_max < m) break;// y_max < m * (n + 1)// floor(y_max / m) <= nn = (unsigned long long)(y_max / m);b = (unsigned long long)(y_max % m);std::swap(m, a);}return ans;}} // namespace internal} // namespace atcoder#line 1 "library/atcoder/internal_type_traits.hpp"#line 7 "library/atcoder/internal_type_traits.hpp"namespace atcoder {namespace internal {#ifndef _MSC_VERtemplate <class T>using is_signed_int128 =typename std::conditional<std::is_same<T, __int128_t>::value ||std::is_same<T, __int128>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int128 =typename std::conditional<std::is_same<T, __uint128_t>::value ||std::is_same<T, unsigned __int128>::value,std::true_type,std::false_type>::type;template <class T>using make_unsigned_int128 =typename std::conditional<std::is_same<T, __int128_t>::value,__uint128_t,unsigned __int128>;template <class T>using is_integral = typename std::conditional<std::is_integral<T>::value ||is_signed_int128<T>::value ||is_unsigned_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using is_signed_int = typename std::conditional<(is_integral<T>::value &&std::is_signed<T>::value) ||is_signed_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int =typename std::conditional<(is_integral<T>::value &&std::is_unsigned<T>::value) ||is_unsigned_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using to_unsigned = typename std::conditional<is_signed_int128<T>::value,make_unsigned_int128<T>,typename std::conditional<std::is_signed<T>::value,std::make_unsigned<T>,std::common_type<T>>::type>::type;#elsetemplate <class T> using is_integral = typename std::is_integral<T>;template <class T>using is_signed_int =typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int =typename std::conditional<is_integral<T>::value &&std::is_unsigned<T>::value,std::true_type,std::false_type>::type;template <class T>using to_unsigned = typename std::conditional<is_signed_int<T>::value,std::make_unsigned<T>,std::common_type<T>>::type;#endiftemplate <class T>using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;template <class T>using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;template <class T> using to_unsigned_t = typename to_unsigned<T>::type;} // namespace internal} // namespace atcoder#line 14 "library/atcoder/modint.hpp"namespace atcoder {namespace internal {struct modint_base {};struct static_modint_base : modint_base {};template <class T> using is_modint = std::is_base_of<modint_base, T>;template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;} // namespace internaltemplate <int m, std::enable_if_t<(1 <= m)>* = nullptr>struct static_modint : internal::static_modint_base {using mint = static_modint;public:static constexpr int mod() { return m; }static mint raw(int v) {mint x;x._v = v;return x;}static_modint() : _v(0) {}template <class T, internal::is_signed_int_t<T>* = nullptr>static_modint(T v) {long long x = (long long)(v % (long long)(umod()));if (x < 0) x += umod();_v = (unsigned int)(x);}template <class T, internal::is_unsigned_int_t<T>* = nullptr>static_modint(T v) {_v = (unsigned int)(v % umod());}unsigned int val() const { return _v; }mint& operator++() {_v++;if (_v == umod()) _v = 0;return *this;}mint& operator--() {if (_v == 0) _v = umod();_v--;return *this;}mint operator++(int) {mint result = *this;++*this;return result;}mint operator--(int) {mint result = *this;--*this;return result;}mint& operator+=(const mint& rhs) {_v += rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator-=(const mint& rhs) {_v -= rhs._v;if (_v >= umod()) _v += umod();return *this;}mint& operator*=(const mint& rhs) {unsigned long long z = _v;z *= rhs._v;_v = (unsigned int)(z % umod());return *this;}mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }mint operator+() const { return *this; }mint operator-() const { return mint() - *this; }mint pow(long long n) const {assert(0 <= n);mint x = *this, r = 1;while (n) {if (n & 1) r *= x;x *= x;n >>= 1;}return r;}mint inv() const {if (prime) {assert(_v);return pow(umod() - 2);} else {auto eg = internal::inv_gcd(_v, m);assert(eg.first == 1);return eg.second;}}friend mint operator+(const mint& lhs, const mint& rhs) {return mint(lhs) += rhs;}friend mint operator-(const mint& lhs, const mint& rhs) {return mint(lhs) -= rhs;}friend mint operator*(const mint& lhs, const mint& rhs) {return mint(lhs) *= rhs;}friend mint operator/(const mint& lhs, const mint& rhs) {return mint(lhs) /= rhs;}friend bool operator==(const mint& lhs, const mint& rhs) {return lhs._v == rhs._v;}friend bool operator!=(const mint& lhs, const mint& rhs) {return lhs._v != rhs._v;}private:unsigned int _v;static constexpr unsigned int umod() { return m; }static constexpr bool prime = internal::is_prime<m>;};template <int id> struct dynamic_modint : internal::modint_base {using mint = dynamic_modint;public:static int mod() { return (int)(bt.umod()); }static void set_mod(int m) {assert(1 <= m);bt = internal::barrett(m);}static mint raw(int v) {mint x;x._v = v;return x;}dynamic_modint() : _v(0) {}template <class T, internal::is_signed_int_t<T>* = nullptr>dynamic_modint(T v) {long long x = (long long)(v % (long long)(mod()));if (x < 0) x += mod();_v = (unsigned int)(x);}template <class T, internal::is_unsigned_int_t<T>* = nullptr>dynamic_modint(T v) {_v = (unsigned int)(v % mod());}unsigned int val() const { return _v; }mint& operator++() {_v++;if (_v == umod()) _v = 0;return *this;}mint& operator--() {if (_v == 0) _v = umod();_v--;return *this;}mint operator++(int) {mint result = *this;++*this;return result;}mint operator--(int) {mint result = *this;--*this;return result;}mint& operator+=(const mint& rhs) {_v += rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator-=(const mint& rhs) {_v += mod() - rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator*=(const mint& rhs) {_v = bt.mul(_v, rhs._v);return *this;}mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }mint operator+() const { return *this; }mint operator-() const { return mint() - *this; }mint pow(long long n) const {assert(0 <= n);mint x = *this, r = 1;while (n) {if (n & 1) r *= x;x *= x;n >>= 1;}return r;}mint inv() const {auto eg = internal::inv_gcd(_v, mod());assert(eg.first == 1);return eg.second;}friend mint operator+(const mint& lhs, const mint& rhs) {return mint(lhs) += rhs;}friend mint operator-(const mint& lhs, const mint& rhs) {return mint(lhs) -= rhs;}friend mint operator*(const mint& lhs, const mint& rhs) {return mint(lhs) *= rhs;}friend mint operator/(const mint& lhs, const mint& rhs) {return mint(lhs) /= rhs;}friend bool operator==(const mint& lhs, const mint& rhs) {return lhs._v == rhs._v;}friend bool operator!=(const mint& lhs, const mint& rhs) {return lhs._v != rhs._v;}private:unsigned int _v;static internal::barrett bt;static unsigned int umod() { return bt.umod(); }};template <int id> internal::barrett dynamic_modint<id>::bt(998244353);using modint998244353 = static_modint<998244353>;using modint1000000007 = static_modint<1000000007>;using modint = dynamic_modint<-1>;namespace internal {template <class T>using is_static_modint = std::is_base_of<internal::static_modint_base, T>;template <class T>using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;template <class> struct is_dynamic_modint : public std::false_type {};template <int id>struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};template <class T>using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;} // namespace internal} // namespace atcoder#line 10 "library/gandalfr/other/io_supporter.hpp"template <typename T>std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {for (int i = 0; i < (int)v.size(); i++)os << v[i] << (i + 1 != (int)v.size() ? " " : "");return os;}template <typename T>std::ostream &operator<<(std::ostream &os, const std::set<T> &st) {for (const T &x : st) {std::cout << x << " ";}return os;}template <typename T>std::ostream &operator<<(std::ostream &os, const std::multiset<T> &st) {for (const T &x : st) {std::cout << x << " ";}return os;}template <typename T>std::ostream &operator<<(std::ostream &os, const std::deque<T> &dq) {for (const T &x : dq) {std::cout << x << " ";}return os;}template <typename T1, typename T2>std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &p) {os << p.first << ' ' << p.second;return os;}template <typename T>std::ostream &operator<<(std::ostream &os, std::queue<T> &q) {int sz = q.size();while (--sz) {os << q.front() << ' ';q.push(q.front());q.pop();}os << q.front();q.push(q.front());q.pop();return os;}namespace atcoder {template <int m>std::ostream &operator<<(std::ostream &os, const static_modint<m> &mi) {os << mi.val();return os;}template <int m>std::ostream &operator<<(std::ostream &os, const dynamic_modint<m> &mi) {os << mi.val();return os;}}template <typename T>std::istream &operator>>(std::istream &is, std::vector<T> &v) {for (T &in : v)is >> in;return is;}template <typename T1, typename T2>std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {is >> p.first >> p.second;return is;}namespace atcoder {template <int m>std::istream &operator>>(std::istream &is, static_modint<m> &mi) {long long n;is >> n;mi = n;return is;}template <int m>std::istream &operator>>(std::istream &is, dynamic_modint<m> &mi) {long long n;is >> n;mi = n;return is;}}#line 4 "playspace/main.cpp"using namespace std;using ll = long long;const int INF = 1001001001;const ll INFLL = 1001001001001001001;const ll MOD = 1000000007;const ll _MOD = 998244353;#define rep(i, j, n) for(ll i = (ll)(j); i < (ll)(n); i++)#define rrep(i, j, n) for(ll i = (ll)(n-1); i >= (ll)(j); i--)#define all(a) (a).begin(),(a).end()#define debug(a) std::cerr << #a << ": " << a << std::endl#define LF cout << endltemplate<typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }template<typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }void Yes(bool ok){ std::cout << (ok ? "Yes" : "No") << std::endl; }int main(void){int T;cin >> T;while (T--) {int N, M;cin >> N >> M;using mint = atcoder::modint998244353;matrix<mint> mt(3, 3);mt.row_assign(0, {1, N, (N >= 3 ? (mint)N * (N - 3) / 2 : 0)});mt.row_assign(1, {1, N - 1, (mint)(N - 2) * (N - 3) / 2});mt.row_assign(2, {1, N - 2, 1 + (N >= 3 ? (mint)(N - 3) * (N - 4) / 2 : 0)});matrix<mint> base(1, 3), sum(3, 1, 1);base.row_assign(0, {1, N, (N >= 3 ? (mint)N * (N - 3) / 2 : 0)});cout << (base * (mt ^ (M - 1)) * sum)(0, 0) << endl;}}