#include <bits/stdc++.h>
using namespace std;
struct SegmentTree {
 private:
  int n;
  vector<int> node;

 public:
  SegmentTree(int sz) {
    n = 1;
    while (n < sz) n *= 2;
    node.resize(2 * n - 1, 0);
  }
  int getmax(int x) {
    x += (n - 1);
    int ans = node[x];
    while (x > 0) {
      x = (x - 1) / 2;
      ans = max(ans, node[x]);
    }
    return ans;
  }
  void update(int a, int b, int x, int k = 0, int l = 0, int r = -1) {
    if (r < 0) r = n;
    if (r <= a || b <= l) return;
    if (a <= l && r <= b) {
      node[k] = max(node[k], x);
      return;
    }
    update(a, b, x, 2 * k + 1, l, (l + r) / 2);
    update(a, b, x, 2 * k + 2, (l + r) / 2, r);
  }
};
struct LazySegmentTree {
 private:
  int n;
  vector<int> node, lazy;

 public:
  LazySegmentTree(int sz) {
    n = 1;
    while (n < sz) n *= 2;
    node.resize(2 * n - 1, 0);
    lazy.resize(2 * n - 1, 0);
  }
  void eval(int k, int l, int r) {
    if (lazy[k] != 0) {
      node[k] += lazy[k];
      if (r - l > 1) {
        lazy[2 * k + 1] += lazy[k] / 2;
        lazy[2 * k + 2] += lazy[k] / 2;
      }
      lazy[k] = 0;
    }
  }
  void add(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0) r = n;
    eval(k, l, r);
    if (b <= l || r <= a) return;
    if (a <= l && r <= b) {
      lazy[k] += r - l;
      eval(k, l, r);
    } else {
      add(a, b, 2 * k + 1, l, (l + r) / 2);
      add(a, b, 2 * k + 2, (l + r) / 2, r);
      node[k] = node[2 * k + 1] + node[2 * k + 2];
    }
  }
  int getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0) r = n;
    if (b <= l || r <= a) return 0;
    eval(k, l, r);
    if (a <= l && r <= b) return node[k];
    int vl = getsum(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getsum(a, b, 2 * k + 2, (l + r) / 2, r);
    return vl + vr;
  }
};
struct sct {
  int l;
  int r;
};
int main() {
  int n;
  cin >> n;
  vector<int> a(n), b(n), c(n);
  for (int i = 0; i < n; i++) cin >> a[i];
  long long fact = 1;
  for (int i = 0; i < n; i++) {
    if (a[i] != 1) goto next;
  }
  for (int i = 1; i <= n; i++) fact = fact * i % 998244353;
  cout << fact << endl;
  return 0;
next:;
  if (a[0] == 1 && a[n - 1] == 1) {
    for (int i = 1; i < n; i++) {
      if (a[i - 1] != 1 && a[i] == 1) {
        for (int j = 0; j < n; j++) {
          b[j] = a[(i + j) % n];
        }
        break;
      }
    }
  } else {
    for (int i = 0; i < n; i++) {
      if (a[i] == 1) {
        for (int j = 0; j < n; j++) {
          b[j] = a[(i + j) % n];
        }
        break;
      }
    }
  }
  map<int, sct> mita;
  mita[1] = {0, -1};
  int lgth = 0;
  for (int i = 0; i < n - 1; i++) {
    if (b[i] == 1) lgth++;
    if (b[i] != b[i + 1]) {
      mita[b[i]].r = i;
      auto itr = mita.find(b[i + 1]);
      if (itr != mita.end()) {
        cout << 0 << endl;
        return 0;
      }
      mita[b[i + 1]] = {i + 1, -1};
    }
  }
  if (b[n - 1] == 1) lgth++;
  mita[b[n - 1]].r = n - 1;
  SegmentTree seg1(n);
  for (auto &p : mita) {
    if (p.second.r - p.second.l + 1 > lgth) {
      cout << 0 << endl;
      return 0;
    }
    seg1.update(max(0, p.second.l - lgth + 1), p.second.r + 1, p.first);
  }
  for (int i = 0; i < n; i++) c[i] = seg1.getmax(i);
  map<int, sct> aki;
  aki[1] = {0, -1};
  for (int i = 0; i < n - 1; i++) {
    if (c[i] != c[i + 1]) {
      aki[c[i]].r = i;
      aki[c[i + 1]] = {i + 1, -1};
    }
  }
  aki[c[n - 1]].r = n - 1;
  LazySegmentTree seg2(n);
  long long ans = 1, nokori = 0;
  for (int i = 1; i <= n; i++) {
    auto itr1 = mita.find(i), itr2 = aki.find(i);
    if (itr1 == mita.end()) {
      ans = (ans * nokori) % 998244353;
      nokori--;
    } else {
      int l1 = itr1->second.l, r1 = itr1->second.r;
      int l2 = itr2->second.l, r2 = itr2->second.r;
      seg2.add(l2, r2 + 1);
      ans = (ans * seg2.getsum(r1 - lgth + 1, l1 + 1)) % 998244353;
      nokori += r2 - l2;
    }
  }
  cout << ans << endl;
  return 0;
}
