description: n people gathered to hold a jury meeting of the upcoming competition, the i-th member of the jury came up with a_i tasks, which they want to share with each other.
  
  First, the jury decides on the order which they will follow while describing the tasks. Let that be a permutation p of numbers from 1 to n (an array of size n where each integer from 1 to n occurs exactly once).
  
  Then the discussion goes as follows:
  
    * If a jury member p_1 has some tasks left to tell, then they tell one task to others. Otherwise, they are skipped. 
    * If a jury member p_2 has some tasks left to tell, then they tell one task to others. Otherwise, they are skipped. 
    * ... 
    * If a jury member p_n has some tasks left to tell, then they tell one task to others. Otherwise, they are skipped. 
    * If there are still members with tasks left, then the process repeats from the start. Otherwise, the discussion ends. 
  
  
  
  A permutation p is nice if none of the jury members tell two or more of their own tasks in a row. 
  
  Count the number of nice permutations. The answer may be really large, so print it modulo 998 244 353.
  
  Input
  
  The first line contains a single integer t (1 ≤ t ≤ 10^4) — the number of test cases.
  
  The first line of the test case contains a single integer n (2 ≤ n ≤ 2 ⋅ 10^5) — number of jury members.
  
  The second line contains n integers a_1, a_2, ..., a_n (1 ≤ a_i ≤ 10^9) — the number of problems that the i-th member of the jury came up with.
  
  The sum of n over all test cases does not exceed 2 ⋅ 10^5.
  
  Output
  
  For each test case, print one integer — the number of nice permutations, taken modulo 998 244 353.
  
  Example
  
  Input
  
  
  4
  2
  1 2
  3
  5 5 5
  4
  1 3 3 7
  6
  3 4 2 1 3 3
  
  
  Output
  
  
  1
  6
  0
  540
  
  Note
  
  Explanation of the first test case from the example:
  
  There are two possible permutations, p = [1, 2] and p = [2, 1]. For p = [1, 2], the process is the following:
  
    1. the first jury member tells a task; 
    2. the second jury member tells a task; 
    3. the first jury member doesn't have any tasks left to tell, so they are skipped; 
    4. the second jury member tells a task. 
  
  
  
  So, the second jury member has told two tasks in a row (in succession), so the permutation is not nice.
  
  For p = [2, 1], the process is the following:
  
    1. the second jury member tells a task; 
    2. the first jury member tells a task; 
    3. the second jury member tells a task. 
  
  
  
  So, this permutation is nice.
solution: import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.PrintWriter;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.StringTokenizer;
  import java.util.TreeMap;
  import java.util.TreeSet;
  import java.util.concurrent.CopyOnWriteArrayList;
  import java.util.stream.Collectors;
  
  
  public class Main implements Runnable {
      int n, m, k;
      long n1, s;
      static boolean use_n_tests = true;
      long mod = 1_000_000_007;
      static long mod1 = 998244353L;
      List<Integer> primes = Collections.emptyList();//generatePrimes(31623);
      static long[] factorial = new long[200001];
      static Coeff coeff = new Coeff(200001, mod1);
      static {
          factorial[0] = 1;
          for (int i = 1; i <= 200000; i++) {
              factorial[i] = i * 1l * factorial[i - 1];
              factorial[i] %= mod1;
          }
      }
  
      void solve(FastScanner in, PrintWriter out, int testNumber) {
          n = in.nextInt();
          Integer[] a = in.nextArray2(n);
          Map<Integer, Integer> cnt = new HashMap<>();
          for (Integer integer : a) {
              cnt.merge(integer, 1, Integer::sum);
          }
          Arrays.sort(a);
          int last = a[n - 1];
          int prelast = a[n - 2];
          if (last - prelast > 1) {
              out.println(0);
          } else if (last - prelast == 0) {
              out.println(factorial[n]);
          } else {
              long ans = factorial[n];
              int prelastCount = cnt.get(prelast);
              long base = coeff.C(n, prelastCount + 1);
              base *= factorial[prelastCount];
              base %= mod1;
  
              long rem = factorial[n - prelastCount - 1];
              base *= rem;
              base %= mod1;
  
              ans -= base;
              ans += mod1;
              ans %= mod1;
              out.println(ans);
          }
      }
  
      // ****************************** template code ***********
  
      static public class LcaSparseTable {
          int len;
          int[][] up;
          int[] tin;
          int[] tout;
          int time;
          static List<Integer>[] tree;
          static LcaSparseTable t;
  
          void dfs(List<Integer>[] tree, int u, int p) {
              tin[u] = time++;
              up[0][u] = p;
              for (int i = 1; i < len; i++)
                  up[i][u] = up[i - 1][up[i - 1][u]];
              for (int v : tree[u])
                  if (v != p)
                      dfs(tree, v, u);
              tout[u] = time++;
          }
  
          public LcaSparseTable(List<Integer>[] tree, int root) {
              int n = tree.length;
              len = 1;
              while ((1 << len) <= n) ++len;
              up = new int[len][n];
              tin = new int[n];
              tout = new int[n];
              dfs(tree, root, root);
          }
  
          boolean isParent(int parent, int child) {
              return tin[parent] <= tin[child] && tout[child] <= tout[parent];
          }
  
          public int lca(int a, int b) {
              if (isParent(a, b))
                  return a;
              if (isParent(b, a))
                  return b;
              for (int i = len - 1; i >= 0; i--)
                  if (!isParent(up[i][a], b))
                      a = up[i][a];
              return up[0][a];
          }
  
          public static void adaptGraph(Graph graph) {
              int n = graph.size() + 1;
              tree = new List[n];
              for (int i = 0; i < n; i++) {
                  tree[i] = new ArrayList<>();
              }
              List<Integer> edges = graph.getEdges();
              for (int i = 0; i < edges.size() / 2; i++) {
                  int v = edges.get(i * 2);
                  int u = edges.get(i * 2 + 1);
                  tree[v].add(u);
                  tree[u].add(v);
              }
              t = new LcaSparseTable(tree, 0);
          }
  
          public static int getLca(int a, int b) {
              return t.lca(a, b);
          }
      }
  
  
      List<Integer> factorize(int a) {
          List<Integer> res = new ArrayList<>();
          for (int i = 0; i < primes.size(); i++) {
              int p = primes.get(i);
              while (a % p == 0) {
                  res.add(p);
                  a /= p;
              }
              if (a == 1 && p > a) {
                  break;
              }
          }
          if (a != 1) {
              res.add(a);
          }
          return res;
      }
  
      void impossible() {
          out.println(-1);
      }
  
      void yes() {
          out.println("YES");
      }
  
      void no() {
          out.println("NO");
      }
  
      static boolean next_permutation(char[] p) {
          for (int a = p.length - 2; a >= 0; --a)
              if (p[a] < p[a + 1])
                  for (int b = p.length - 1; ; --b)
                      if (p[b] > p[a]) {
                          char t = p[a];
                          p[a] = p[b];
                          p[b] = t;
                          for (++a, b = p.length - 1; a < b; ++a, --b) {
                              t = p[a];
                              p[a] = p[b];
                              p[b] = t;
                          }
                          return true;
                      }
          return false;
      }
  
      public static class DisjointSets {
          int[] p;
  
          DisjointSets(int size) {
              p = new int[size];
              for (int i = 0; i < size; i++)
                  p[i] = i;
          }
  
          public int root(int x) {
              return x == p[x] ? x : (p[x] = root(p[x]));
          }
  
          public void unite(int a, int b) {
              a = root(a);
              b = root(b);
              if (a != b)
                  p[a] = b;
          }
      }
  
      boolean triangleCheck(int a, int b, int c) {
          return a + b > c && a + c > b && b + c > a;
      }
  
      Map<Integer, Integer> numberCompression(List<Integer> ls) {
          Collections.sort(ls);
          int id = 1;
          Map<Integer, Integer> comp = new HashMap<>();
          for (int num : ls) {
              if (!comp.containsKey(num)) {
                  comp.put(num, id++);
              }
          }
          return comp;
      }
  
      long lcm(long a, long b) {
          return (a / gcd(a, b)) * b;
      }
  
      long gcd(long a, long b) {
          return b == 0 ? a : gcd(b, a % b);
      }
  
      class Pt {
          int x, y;
  
          Pt(int x, int y) {
              this.x = x;
              this.y = y;
          }
  
          public int getX() {
              return x;
          }
  
          public int getY() {
              return y;
          }
  
          boolean sameAxis(Pt b) {
              return b.x == x || b.y == y;
          }
  
          int manxDist(Pt b) {
              return Math.abs(x - b.x) + Math.abs(y - b.y);
          }
  
          void read() {
              x = in.nextInt();
              y = in.nextInt();
          }
      }
  
      void swap(Integer[] a, int i, int j) {
          Integer tmp = a[i];
          a[i] = a[j];
          a[j] = tmp;
      }
  
      void swap(List<Integer> a, int i, int j) {
          Integer tmp = a.get(i);
          a.set(i, a.get(j));
          a.set(j, tmp);
      }
  
      long manhDist(long x, long y, long x1, long y1) {
          return Math.abs(x - x1) + Math.abs(y - y1);
      }
  
      double dist(double x, double y, double x1, double y1) {
          return Math.sqrt(Math.pow(x - x1, 2.0) + Math.pow(y - y1, 2.0));
      }
  
      public static class FW {
          public static void add(long[] t, int i, long value) {
              for (; i < t.length; i |= i + 1)
                  t[i] += value;
          }
  
          public static long sum(long[] t, int i) {
              long res = 0;
              for (; i >= 0; i = (i & (i + 1)) - 1)
                  res += t[i];
              return res;
          }
  
          public static void add(long[] t, int a, int b, long value) {
              add(t, a, value);
              add(t, b + 1, -value);
          }
      }
  
      int sign(int a) {
          if (a < 0) {
              return -1;
          }
          return 1;
      }
  
      long binpow(long a, int b) {
          long res = 1;
          while (b != 0) {
              if (b % 2 == 0) {
                  b /= 2;
                  a *= a;
                  a %= mod;
              }
  
              b--;
              res *= a;
              res %= mod;
          }
          return res;
      }
  
      List<Integer> getDigits(long n) {
          List<Integer> res = new ArrayList<>();
          while (n != 0) {
              res.add((int) (n % 10L));
              n /= 10;
          }
          return res;
      }
  
      List<Integer> generatePrimes(int n) {
          List<Integer> res = new ArrayList<>();
          boolean[] sieve = new boolean[n + 1];
          for (int i = 2; i <= n; i++) {
              if (!sieve[i]) {
                  res.add(i);
              }
              if ((long) i * i <= n) {
                  for (int j = i * i; j <= n; j += i) {
                      sieve[j] = true;
                  }
              }
          }
          return res;
      }
  
      static int stack_size = 1 << 29;
  
      static class Coeff {
          long mod;
          long[][] C;
          long[] fact;
          boolean cycleWay = false;
  
          Coeff(int n, long mod) {
              this.mod = mod;
              fact = new long[n + 1];
              fact[0] = 1;
              for (int i = 1; i <= n; i++) {
                  fact[i] = i;
                  fact[i] %= mod;
                  fact[i] *= fact[i - 1];
                  fact[i] %= mod;
              }
          }
  
          Coeff(int n, int m, long mod) {
              // n > m
              cycleWay = true;
              this.mod = mod;
              C = new long[n + 1][m + 1];
              for (int i = 0; i <= n; i++) {
                  for (int j = 0; j <= Math.min(i, m); j++) {
                      if (j == 0 || j == i) {
                          C[i][j] = 1;
                      } else {
                          C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
                          C[i][j] %= mod;
                      }
                  }
              }
          }
  
          public long C(int n, int m) {
              if (cycleWay) {
                  return C[n][m];
              }
              return fC(n, m);
          }
  
          private long fC(int n, int m) {
              return (fact[n] * inv(fact[n - m] * fact[m] % mod)) % mod;
          }
  
          private long inv(long r) {
              if (r == 1)
                  return 1;
              return ((mod - mod / r) * inv(mod % r)) % mod;
          }
      }
  
      class Pair {
          int first;
          long second;
  
          Pair(int f, long s) {
              first = f;
              second = s;
          }
  
          public int getFirst() {
              return first;
          }
  
          public long getSecond() {
              return second;
          }
      }
  
      class MultisetTree<T> {
          int size = 0;
  
          TreeMap<T, Integer> mp = new TreeMap<>();
  
          void add(T x) {
              mp.merge(x, 1, Integer::sum);
              size++;
          }
  
          void remove(T x) {
              if (mp.containsKey(x)) {
                  mp.merge(x, -1, Integer::sum);
                  if (mp.get(x) == 0) {
                      mp.remove(x);
                  }
                  size--;
              }
          }
  
          boolean contains(T x) {
              return mp.containsKey(x);
          }
  
          T greatest() {
              return mp.lastKey();
          }
  
          T higher(T x) {
              return mp.higherKey(x);
          }
  
          T smallest() {
              return mp.firstKey();
          }
  
          T biggest() {
              return mp.lastKey();
          }
  
          int size() {
              return size;
          }
  
          int diffSize() {
              return mp.size();
          }
      }
  
      class Multiset<T> {
          int size = 0;
  
          Map<T, Integer> mp = new HashMap<>();
  
          void add(T x) {
              mp.merge(x, 1, Integer::sum);
              size++;
          }
  
          boolean contains(T x) {
              return mp.containsKey(x);
          }
  
          void remove(T x) {
              if (mp.containsKey(x)) {
                  mp.merge(x, -1, Integer::sum);
                  if (mp.get(x) == 0) {
                      mp.remove(x);
                  }
                  size--;
              }
          }
  
          int size() {
              return size;
          }
  
          int diffSize() {
              return mp.size();
          }
      }
  
      static class Range {
          int l, r;
          int id;
  
          public int getL() {
              return l;
          }
  
          public int getR() {
              return r;
          }
  
          public Range(int l, int r, int id) {
              this.l = l;
              this.r = r;
              this.id = id;
          }
      }
  
      static class Array {
          static Range[] readRanges(int n, FastScanner in) {
              Range[] result = new Range[n];
              for (int i = 0; i < n; i++) {
                  result[i] = new Range(in.nextInt(), in.nextInt(), i);
              }
              return result;
          }
  
          static List<List<Integer>> intInit2D(int n) {
              List<List<Integer>> res = new ArrayList<>();
              for (int i = 0; i < n; i++) {
                  res.add(new ArrayList<>());
              }
              return res;
          }
  
          static boolean isSorted(Integer[] a) {
              for (int i = 0; i < a.length - 1; i++) {
                  if (a[i] > a[i + 1]) {
                      return false;
                  }
              }
              return true;
          }
  
          static public long sum(List<Integer> a) {
              long sum = 0;
              for (int x : a) {
                  sum += x;
              }
              return sum;
          }
  
          static public long sum(int[] a) {
              long sum = 0;
              for (int x : a) {
                  sum += x;
              }
              return sum;
          }
  
          static public long sum(long[] a) {
              long sum = 0;
              for (long x : a) {
                  sum += x;
              }
              return sum;
          }
  
          static public long sum(Integer[] a) {
              long sum = 0;
              for (int x : a) {
                  sum += x;
              }
              return sum;
          }
  
          static public int min(Integer[] a) {
              int mn = Integer.MAX_VALUE;
              for (int x : a) {
                  mn = Math.min(mn, x);
              }
              return mn;
          }
  
          static public int min(int[] a) {
              int mn = Integer.MAX_VALUE;
              for (int x : a) {
                  mn = Math.min(mn, x);
              }
              return mn;
          }
  
          static public int max(Integer[] a) {
              int mx = Integer.MIN_VALUE;
              for (int x : a) {
                  mx = Math.max(mx, x);
              }
              return mx;
          }
  
          static public int max(int[] a) {
              int mx = Integer.MIN_VALUE;
              for (int x : a) {
                  mx = Math.max(mx, x);
              }
              return mx;
          }
  
          static public int[] readint(int n, FastScanner in) {
              int[] out = new int[n];
              for (int i = 0; i < out.length; i++) {
                  out[i] = in.nextInt();
              }
              return out;
          }
      }
  
      class Graph {
          List<List<Integer>> graph;
          List<Integer> edges;
  
          Graph(int n) {
              create(n);
          }
  
          private void create(int n) {
              List<List<Integer>> graph = new ArrayList<>();
              for (int i = 0; i < n; i++) {
                  graph.add(new ArrayList<>());
              }
              this.graph = graph;
              edges = new ArrayList<>();
          }
  
          int size() {
              return graph.size();
          }
  
          List<Integer> abj(int v) {
              return graph.get(v);
          }
  
          void read(int m, FastScanner in) {
              for (int i = 0; i < m; i++) {
                  int v = in.nextInt() - 1;
                  int u = in.nextInt() - 1;
                  graph.get(v).add(u);
              }
          }
  
          void readBi(int m, FastScanner in) {
              for (int i = 0; i < m; i++) {
                  int v = in.nextInt() - 1;
                  int u = in.nextInt() - 1;
                  addEdge(v, u);
              }
          }
  
          public void addEdge(int v, int u) {
              graph.get(v).add(u);
              graph.get(u).add(v);
              edges.add(v);
              edges.add(u);
          }
  
          public List<Integer> getEdges() {
              return edges;
          }
      }
  
      class FastScanner {
          BufferedReader br;
          StringTokenizer st;
  
          public FastScanner(InputStream io) {
              br = new BufferedReader(new InputStreamReader(io));
          }
  
          public String line() {
              String result = "";
              try {
                  result = br.readLine();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              return result;
          }
  
          public String next() {
              while (st == null || !st.hasMoreElements()) {
                  try {
                      st = new StringTokenizer(br.readLine());
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              return st.nextToken();
          }
  
          public char[] nextc() {
              return next().toCharArray();
          }
  
          public int nextInt() {
              return Integer.parseInt(next());
          }
  
          public double nextDouble() {
              return Double.parseDouble(next());
          }
  
          public int[] nextArray(int n) {
              int[] res = new int[n];
              for (int i = 0; i < n; i++) {
                  res[i] = in.nextInt();
              }
              return res;
          }
  
          public int[] nextArray() {
              int n = in.nextInt();
              return nextArray(n);
          }
  
          public long[] nextArrayL(int n) {
              long[] res = new long[n];
              for (int i = 0; i < n; i++) {
                  res[i] = in.nextLong();
              }
              return res;
          }
  
          public Long[] nextArrayL2(int n) {
              Long[] res = new Long[n];
              for (int i = 0; i < n; i++) {
                  res[i] = in.nextLong();
              }
              return res;
          }
  
  
          public Integer[] nextArray2(int n) {
              Integer[] res = new Integer[n];
              for (int i = 0; i < n; i++) {
                  res[i] = in.nextInt();
              }
              return res;
          }
  
          public long nextLong() {
              return Long.parseLong(next());
          }
  
      }
  
      void run_t_tests() {
          int t = in.nextInt();
          int i = 0;
          while (t-- > 0) {
              solve(in, out, i++);
          }
      }
  
      void run_one() {
          solve(in, out, -1);
      }
  
      @Override
      public void run() {
          in = new FastScanner(System.in);
          out = new PrintWriter(System.out);
          if (use_n_tests) {
              run_t_tests();
          } else {
              run_one();
          }
          out.close();
      }
  
      static FastScanner in;
      static PrintWriter out;
  
      public static void main(String[] args) throws InterruptedException {
          Thread thread = new Thread(null, new Main(), "", stack_size);
          thread.start();
          thread.join();
      }
  }