#ifdef LOCAL #define _GLIBCXX_DEBUG #endif #include #define int long long using namespace std; using ll = long long; void solve(); template void println(Args... args) { apply([](auto &&... args) { ((cout << args << ' '), ...); }, tuple(args...)); cout << '\n'; } int32_t main() { cin.tie(nullptr); ios_base::sync_with_stdio(false); int t = 1; cin >> t; for (int tc = 0; tc < t; ++tc) { solve(); } return 0; } template struct ModInt { int value; ModInt() : value(0) {} ModInt(ll v) : value(v % MOD) { if (value < 0) value += MOD; } #ifndef int ModInt(int v) : value(v < 0 ? MOD + v : v) {} #endif ModInt operator+=(ModInt m) { value += m.value; if (value >= MOD) value -= MOD; return value; } ModInt operator-=(ModInt m) { value -= m.value; if (value < 0) value += MOD; return value; } ModInt operator*=(ModInt m) { value = (value * 1LL * m.value) % MOD; return value; } ModInt power(int exp) const { if (exp == 0) return 1; ModInt res = (exp & 1 ? value : 1); ModInt half = power(exp >> 1); return res * half * half; } ModInt operator/=(ModInt m) { return *this *= m.power(MOD - 2); } friend std::istream &operator>>(std::istream &is, ModInt &m) { is >> m.value; return is; } friend std::ostream &operator<<(std::ostream &os, const ModInt &m) { os << m.value; return os; } explicit operator int32_t() const { return value; } explicit operator ll() const { return value; } static int32_t mod() { return MOD; } }; template ModInt operator+(ModInt a, ModInt b) { return a += b; } template ModInt operator-(ModInt a, ModInt b) { return a -= b; } template ModInt operator*(ModInt a, ModInt b) { return a *= b; } template ModInt operator/(ModInt a, ModInt b) { return a /= b; } template ModInt operator==(ModInt a, ModInt b) { return (int32_t) a == (int32_t) b; } template ModInt operator!=(ModInt a, ModInt b) { return (int32_t) a != (int32_t) b; } using mint = ModInt<998244353>; //using mint = ModInt<(int32_t)(1e9 + 7)>; vector f{1}, inv{1}; void precomputeFactorials(int size) { if (f.size() >= size) return; int old = f.size(); f.resize(size, 0); inv.resize(size, 0); for (int i = old; i < size; ++i) f[i] = f[i - 1] * mint(i); inv[size - 1] = mint(1) / f[size - 1]; for (int i = size - 1; i >= old; --i) inv[i - 1] = inv[i] * mint(i); } mint binom(int n, int k) { if (k < 0 || k > n) return 0; return f[n] * inv[k] * inv[n - k]; } mint check(const vector &row, map cnt) { int s = accumulate(row.begin(), row.end(), 0LL); int t = 0; vector lf(row.size()), rg(row.size()); for (int i = 0; i < row.size(); ++i) { lf[i] = t; t += row[i]; s -= row[i]; rg[i] = s; } mint res = 1; for (int i = 0; i < row.size(); ++i) { int mx = max(lf[i], rg[i]); if (cnt[mx] < row[i]) return 0; res *= binom(cnt[mx], row[i]); cnt[mx] -= row[i]; } for (auto [k, v] : cnt) { if (v != 0) return 0; } return res; } void solve() { int n, m; cin >> n >> m; precomputeFactorials(m + 100); vector a(n); for (int &x: a) cin >> x; map t; for (int x: a) t[x]++; vector> cnt(t.begin(), t.end()); reverse(cnt.begin(), cnt.end()); mint ans = 1; vector lfcur, rgcur; vector lf, rg; int lfs = 0, rgs = 0; for (auto &[mx, cn]: cnt) { int mn = n - mx; if (cn + lfs == mn) { lfcur.push_back(cn); lfs += cn; } else if (cn + rgs == mn) { rgcur.push_back(cn); rgs += cn; } else if (cn + lfs + rgs == mn + mn) { lfcur.push_back(mn - lfs); lfs += mn - lfs; rgcur.push_back(mn - rgs); rgs += mn - rgs; } else { return println(0); } if (lfs == rgs) { if (lfcur != rgcur) ans *= 2; for (int x: lfcur) lf.push_back(x); lfcur.clear(); for (int x: rgcur) rg.push_back(x); rgcur.clear(); } } auto concat = lfcur; for (int j = (int) rgcur.size() - 1; j >= 0; --j) concat.push_back(rgcur[j]); auto rconcat = concat; reverse(rconcat.begin(), rconcat.end()); if (concat != rconcat) ans *= 2; for (int x: concat) lf.push_back(x); reverse(rg.begin(), rg.end()); for (int x: rg) lf.push_back(x); mint o = check(lf, t); cout << ans * binom(m, lf.size()) * o << '\n'; }