#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <int n, class... T>
typename enable_if<(n >= sizeof...(T))>::type _ot(ostream &,
                                                  tuple<T...> const &) {}
template <int n, class... T>
typename enable_if<(n < sizeof...(T))>::type _ot(ostream &os,
                                                 tuple<T...> const &t) {
  os << (n == 0 ? "" : ", ") << get<n>(t);
  _ot<n + 1>(os, t);
}
template <class... T>
ostream &operator<<(ostream &o, tuple<T...> const &t) {
  o << "(";
  _ot<0>(o, t);
  o << ")";
  return o;
}
template <class T, class U>
ostream &operator<<(ostream &o, pair<T, U> const &p) {
  o << "(" << p.first << ", " << p.second << ")";
  return o;
}
template <class T>
ostream &operator<<(ostream &o, const stack<T> &a) {
  o << "{";
  for (auto tmp = a; tmp.size(); tmp.pop())
    o << (a.size() == tmp.size() ? "" : ", ") << tmp.top();
  o << "}";
  return o;
}
template <class T,
          class = typename iterator_traits<typename T::iterator>::value_type,
          class = typename enable_if<!is_same<T, string>::value>::type>
ostream &operator<<(ostream &o, const T &a) {
  for (auto ite = a.begin(); ite != a.end(); ++ite)
    o << (ite == a.begin() ? "" : " ") << *ite;
  return o;
}
struct UF {
  int n;
  vector<int> par;
  UF(int n) : n(n), par(n, -1) {}
  int find(int x) { return par[x] < 0 ? x : par[x] = find(par[x]); }
  int size(int x) { return -par[find(x)]; }
  bool same(int a, int b) { return find(a) == find(b); }
  void unite(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) return;
    if (par[a] < par[b]) swap(a, b);
    par[b] += par[a];
    par[a] = b;
  }
};
const int N = 3e5;
const ll mod = 998244353;
int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(0);
  int n;
  cin >> n;
  vector<int> a(n);
  for (int i = 0; i < n; i++) cin >> a[i];
  vector<int> cnt(n + 1), last(n + 1), ecas(n + 1);
  for (int i = 0; i < n; i++) cnt[a[i]]++;
  for (int i = 0; i < n - 1; i++) {
    if (a[i] != a[i + 1]) last[a[i]] = i, ecas[a[i]]++;
  }
  if (a[n - 1] != a[0]) last[a[n - 1]] = n - 1, ecas[a[n - 1]]++;
  for (int i = 1; i <= n; i++)
    if (ecas[i] >= 2) return cout << 0 << endl, 0;
  vector<pair<int, int>> v;
  for (int i = 2; i <= n; i++)
    if (cnt[i]) {
      last[i] += n - last[1] - 1;
      if (last[i] >= n) last[i] -= n;
      v.emplace_back(last[i], i);
    }
  int k = n - cnt[1];
  int x = cnt[1];
  int tapris = v.size();
  sort((v).begin(), (v).end());
  vector<int> rnk(n + 1);
  vector<int> used(n + 1);
  for (int i = 0; i < v.size(); i++) rnk[v[i].second] = i;
  UF uf(tapris);
  vector<pair<int, int>> uku(tapris);
  ll ans = 1;
  ll free = 0;
  for (int i = 2; i <= n; i++) {
    if (cnt[i]) {
      int qina = x - cnt[i] + 1;
      if (qina <= 0) return cout << 0 << endl, 0;
      int p = rnk[i];
      used[p] = 1;
      int ecas = cnt[i];
      if (p - 1 >= 0) {
        if (used[p - 1]) {
          int s, t;
          tie(s, t) = uku[uf.find(p - 1)];
          free -= t;
          ecas += s;
          uf.unite(p - 1, p);
        } else {
          qina = 1;
        }
      }
      if (p + 1 < tapris) {
        if (used[p + 1]) {
          int s, t;
          tie(s, t) = uku[uf.find(p + 1)];
          free -= t;
          ecas += s;
          uf.unite(p + 1, p);
        } else {
          qina = 1;
        }
      }
      int noel;
      if (uf.same(p, tapris - 1) || uf.same(p, 0)) {
        noel = ecas;
      } else {
        noel = max(ecas - (x - 1), 0);
      }
      if (noel <= 0) return cout << 0 << endl, 0;
      uku[uf.find(p)] = make_pair(ecas, noel);
      free += noel;
      ans = ans * qina % mod;
    } else {
      int cap;
      if (free == k) {
        cap = n - 1 - (i - 2);
      } else {
        cap = free - (i - 2);
      }
      if (cap <= 0) return cout << 0 << endl, 0;
      ans = ans * cap % mod;
    }
  }
  cout << ans << endl;
  return 0;
}
