import std.algorithm;
import std.array;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.functional;
import std.string;
import std.traits;

pure
X genericPower(alias mul, X, Y) (X x, Y y, X one = 1.to!X)
  if (isUnsigned!Y) {
  X a = one, b = x;
  while (y > 0) {
    if (y & 1) {
      a = binaryFun!mul (a, b);
    }
    b = binaryFun!mul (b, b);
    y >>>= 1;
  }
  return a;
}

struct IntM(int q = 1_000_000_007) {
  alias N = IntM!q;
  private:
  int v;
  invariant () { assert (v >= 0 && v < q); }
  pure nothrow @nogc
  void fromInt (int m) {
    v = m % q;
    if (v < 0) {
      v += q;
    }
  }
  public:
  pure nothrow @nogc
  this (int m) {
    fromInt (m);
  }
  pure nothrow @nogc
  N opAssign (int m) {
    fromInt (m);
    return this;
  }
  pure nothrow @nogc
  N opUnary (string op : "-")() const {
    return N (-v);
  }
  pure nothrow @nogc
  ref N opUnary (string op : "++")() {
    if (++v >= q) {
      v -= q;
    }
    return this;
  }
  pure nothrow @nogc
  ref N opUnary (string op : "--")() {
    if (--v < 0) {
      v += q;
    }
    return this;
  }
  pure nothrow @nogc
  ref N opOpAssign (string op : "+")(in N rhs) {
    v = (v + rhs.v) % q;
    return this;
  }
  pure nothrow @nogc
  ref N opOpAssign (string op : "-")(in N rhs) {
    v = (v - rhs.v + q) % q;
    return this;
  }
  pure nothrow @nogc
  ref N opOpAssign (string op : "*")(in N rhs) {
    v = (v.to!(long) * rhs.v) % q;
    return this;
  }
  pure nothrow @nogc
  ref N opOpAssign (string op : "/")(in N rhs) {
    return this *= rhs.inversion ();
  }
  pure nothrow @nogc
  ref N opOpAssign (string op)(in int rhs) if (op == "+" || op == "-" || op == "*" || op == "/") {
    mixin ("return this " ~ op ~ "= N(rhs);");
  }
  pure nothrow @nogc
  N opBinary (string op)(in N rhs) const if (op == "+" || op == "-" || op == "*" || op == "/") {
    N t = this;
    mixin ("t " ~ op ~ "= rhs;");
    return t;
  }
  pure nothrow @nogc
  N opBinary (string op)(in int rhs) const if (op == "+" || op == "-" || op == "*" || op == "/") {
    mixin ("return this " ~ op ~ " N(rhs);");
  }
  pure nothrow @nogc
  N opBinaryRight (string op)(in int rhs) const if (op == "+" || op == "*") {
    mixin ("return this " ~ op ~ " N(rhs);");
  }
  pure nothrow @nogc
  N opBinary (string op : "^^")(in ulong rhs) const {
    return genericPower! ("a * b", N, ulong) (this, rhs);
  }
  pure nothrow @nogc
  int opCast(T : int)() const { return v; }
}


alias N = IntM!998244353;

int test () {
  int n;
  readf (" %d", &n);
  auto d = new int[n];
  foreach (i; 0 .. n) {
    readf (" %d", &d[i]);
  }
  if (d[0] != 0) {
    return 0;
  }
  auto c = new int[n];
  foreach (i; 0 .. n) {
    ++c[d[i]];
  }
  debug stderr.writeln (c);
  if (c[0] != 1) {
    return 0;
  }
  N res = 1;
  foreach (i; 1 .. n) {
    if (c[i-1] > 0) {
      res *= N (c[i-1]) ^^ c[i];
    }
  }
  return res.to!int;
}

void main() {
  writeln (test ());
}

