#include <bits/stdc++.h>
using namespace std;
const long long MOD = 998244353;
template <class T>
inline bool MX(T &l, const T &r) {
  return l < r ? l = r, 1 : 0;
}
template <class T>
inline bool MN(T &l, const T &r) {
  return l > r ? l = r, 1 : 0;
}
int N;
int A[314514];
int B[314514];
long long rev[314514];
long long fact[314514];
struct MinOp {
  const static long long INF = 1LL << 61;
  const static auto e = INF;
  static long long apply(pair<long long, long long> &f, long long v,
                         long long w) {
    return f.first * v + f.second;
  };
  static long long mergev(long long a, long long b) { return min(a, b); };
  static pair<long long, long long> mergef(pair<long long, long long> &f,
                                           pair<long long, long long> &g) {
    return pair<long long, long long>(f.first * g.first,
                                      f.first * g.second + f.second);
  };
};
struct SumOp {
  const static auto e = 0LL;
  static long long apply(pair<long long, long long> &f, long long v,
                         long long w) {
    return (f.first * v + f.second * w) % MOD;
  };
  static long long mergev(long long a, long long b) {
    long long ret = a + b;
    while (ret >= MOD) ret -= MOD;
    return ret;
  };
  static pair<long long, long long> mergef(pair<long long, long long> &f,
                                           pair<long long, long long> &g) {
    return pair<long long, long long>((f.first * g.first) % MOD,
                                      (f.first * g.second + f.second) % MOD);
  };
};
template <class OP>
struct LazySeg {
  int size;
  vector<char> has_lazy;
  vector<long long> seg;
  vector<long long> width;
  vector<pair<long long, long long> > lazy;
  LazySeg() {}
  LazySeg(vector<long long> A) { Init(A); }
  void Init(vector<long long> A) {
    int n = A.size();
    size = 1;
    while (size < n) size *= 2;
    seg.resize(size);
    seg.insert(seg.end(), A.begin(), A.end());
    seg.resize(size * 2);
    lazy.resize(size * 2);
    has_lazy.resize(size * 2);
    width.resize(size * 2, 1);
    for (int(i) = (size)-1; (i) >= 0; --(i)) {
      seg[i] = OP::mergev(seg[i * 2], seg[i * 2 + 1]);
      width[i] = width[i * 2] + width[i * 2 + 1];
    }
  }
  void LazyPropagate(int k) {
    if (has_lazy[k]) {
      seg[k] = OP::apply(lazy[k], seg[k], width[k]);
      if (k < size) {
        for (int(i) = 0; (i) < (2); ++(i)) {
          if (has_lazy[k * 2 + i]) {
            lazy[k * 2 + i] = OP::mergef(lazy[k], lazy[k * 2 + i]);
          } else {
            lazy[k * 2 + i] = lazy[k];
          }
          has_lazy[k * 2 + i] = true;
        }
      }
      has_lazy[k] = false;
    }
  }
  void Apply(int wishl, int wishr, int k, int watchl, int watchr, long long a,
             long long b) {
    if (wishr <= watchl || watchr <= wishl) {
      LazyPropagate(k);
      return;
    }
    if (wishl <= watchl && watchr <= wishr) {
      pair<long long, long long> p(a, b);
      if (has_lazy[k]) {
        lazy[k] = OP::mergef(p, lazy[k]);
      } else {
        lazy[k] = p;
      }
      has_lazy[k] = true;
      LazyPropagate(k);
      return;
    }
    LazyPropagate(k);
    int mid = (watchl + watchr) / 2;
    Apply(wishl, wishr, k * 2, watchl, mid, a, b);
    Apply(wishl, wishr, k * 2 + 1, mid, watchr, a, b);
    seg[k] = OP::mergev(seg[k * 2], seg[k * 2 + 1]);
  }
  void Apply(int wishl, int wishr, long long a, long long b) {
    return Apply(wishl, wishr, 1, 0, size, a, b);
  }
  long long Get(int wishl, int wishr, int k, int watchl, int watchr) {
    long long lval, rval;
    if (wishr <= watchl || watchr <= wishl) return OP::e;
    if (wishl <= watchl && watchr <= wishr) {
      LazyPropagate(k);
      return seg[k];
    }
    LazyPropagate(k);
    int mid = (watchl + watchr) / 2;
    lval = Get(wishl, wishr, k * 2, watchl, mid);
    rval = Get(wishl, wishr, k * 2 + 1, mid, watchr);
    return OP::mergev(lval, rval);
  }
  long long Get(int wishl, int wishr) { return Get(wishl, wishr, 1, 0, size); }
};
struct Range {
  vector<pair<int, int> > segs;
  void And(int l, int r) {
    if (l >= 0) {
      vector<pair<int, int> > nsegs;
      for (pair<int, int> p : segs) {
        MX(p.first, l);
        MN(p.second, r);
        if (p.first < p.second) nsegs.emplace_back(p);
      }
      segs.swap(nsegs);
    } else {
      vector<pair<int, int> > nsegs;
      for (pair<int, int> p : segs) {
        MX(p.first, 0);
        MN(p.second, r);
        if (p.first < p.second) nsegs.emplace_back(p);
      }
      for (pair<int, int> p : segs) {
        MX(p.first, l + N);
        MN(p.second, N);
        if (p.first < p.second) nsegs.emplace_back(p);
      }
      segs.swap(nsegs);
      for (pair<int, int> p : segs) {
        for (pair<int, int> q : segs) {
          if (p == q) continue;
          assert(!(max(p.first, q.first) < min(p.second, q.second)));
        }
      }
    }
    assert(segs.size() <= 3);
  }
};
Range rang[314514];
signed main() {
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(0);
  cin >> N;
  bool all1 = true;
  int shift = -1;
  fact[0] = 1;
  for (int(i) = 0; (i) < (N); ++(i)) {
    cin >> A[i];
    all1 &= A[i] == 1;
    fact[i + 1] = fact[i] * (i + 1) % MOD;
    if (A[i] != 1) shift = i;
  }
  if (all1) {
    cout << fact[N] << endl;
    return 0;
  }
  assert(shift >= 0);
  int M = 0;
  vector<pair<int, int> > ps;
  for (int(i) = 0; (i) < (N); ++(i)) {
    B[i] = A[(i + N - shift) % N];
    MX(M, B[i]);
    ps.emplace_back(pair<int, int>(B[i], i));
  }
  sort((ps).begin(), (ps).end());
  vector<int> cnts;
  int cnt = 0;
  for (int(i) = 0; (i) < (N); ++(i)) {
    if (B[i] == 1) {
      cnt++;
    } else {
      if (cnt > 0) cnts.emplace_back(cnt);
      cnt = 0;
    }
  }
  if (cnt > 0) cnts.emplace_back(cnt);
  if (cnts.size() != 1) {
    cout << "0" << endl;
    return 0;
  }
  int t = cnts[0] - 1;
  int rem = N - M;
  for (int(i) = (M + 1) - 1; (i) >= (1); --(i)) {
    rang[i].segs.emplace_back(pair<int, int>(0, N));
  }
  for (int(i) = (N)-1; (i) >= 0; --(i)) {
    int val, idx;
    tie(val, idx) = ps[i];
    int l = idx - t;
    rang[val].And(l, idx + 1);
  }
  LazySeg<SumOp> poss(vector<long long>(N, 1));
  long long ans = fact[rem];
  for (int(i) = (N)-1; (i) >= 0; --(i)) {
    int val, idx;
    tie(val, idx) = ps[i];
    int l = idx - t;
    if (i + 1 == N || ps[i + 1].first != val) {
      long long cnt = 0;
      for (auto &p : rang[val].segs) {
        cnt += poss.Get(p.first, p.second);
      }
      ans *= cnt;
    }
    if (l < 0) {
      assert(l + N >= 0 && l + N < N);
      poss.Apply(0, idx + 1, 0, 0);
      poss.Apply(l + N, N, 0, 0);
    } else {
      poss.Apply(l, idx + 1, 0, 0);
    }
  }
  if (t > N - M) assert(ans == 0);
  cout << ans << endl;
}
