#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <utility>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <math.h>
#include <iomanip>
using namespace std;
#define forr(i,a,b,c) for(int i=a;i<b;i+=c)
#define forrb(i,a,b,c) for(int i=a;i>b;i-=c)
#define fori(i,n) forr(i,0,n,1)
#define forib(i,n) forrb(i,n-1,-1,1)
#define forn(i,n) forr(i,1,n,1)
#define fornb(i,n) forrb(i,n-1,0,1)
#define fort(i,m,n) forr(i,m,n,1)
#define fortb(i,m,n) forrb(i,n-1,m-1,1)
#define forin(i,arr) fori(i,arr.size())
#define forinb(i,arr) forib(i,arr.size())
#define forrl(i,a,b,c) for(lol i=a;i<b;i+=c)
#define forrbl(i,a,b,c) for(lol i=a;i>b;i-=c)
#define foril(i,n) forrl(i,0,n,1)
#define foribl(i,n) forrbl(i,n-1,-1,1)
#define fornl(i,n) forrl(i,1,n,1)
#define fornbl(i,n) forrbl(i,n-1,0,1)
#define fortl(i,m,n) forrl(i,m,n,1)
#define fortbl(i,m,n) forrbl(i,n-1,m-1,1)
#define forinl(i,arr) foril(i,arr.size())
#define forinbl(i,arr) foribl(i,arr.size())
#define into(i) cin >> i;
#define def(i) lol i; into(i)
#define deft(t,i) t i; into(i)
#define defl(i) lol i; into(i)
#define defs(i) string i; into(i)
#define defn def(n)
#define defp def(p)
#define defm def(m)
#define defk def(k)
#define defa def(a)
#define defb def(b)
#define defc def(c)
#define defd def(d)
#define vec(a) vector<a>
#define co cout <<
#define out(a) cout << a <<' ';
#define el << endl;
#define ell << '\n';
#define outv(arr,n) fori(i,n){out(arr[i])} co "" el
#define cas(p) co "Case #" << p+1 <<": ";
#define ex return 0;
#define qii queue<int>
#define sti stack<int>
#define dei deque<int>
#define con continue;
#define br break;
#define maxi 1000000007
#define lmaxi 100000000000000007
#define mod %maxi
#define wne(arr) while(!arr.empty())
#define all(arr) arr.begin(),arr.end()
typedef vector<int> veci;
typedef long long lol;
typedef unsigned long long ulol;
typedef vector<lol> vecl;
#define table(name,n,m) vector<veci> name(n,veci (m));
#define tablel(name,n,m) vector<vecl> name(n,vecl (m));
typedef pair<lol, lol> point;
typedef pair<point, point> poin;
typedef pair<lol, point> poing;
typedef pair<point, lol> poinf;
typedef vector<point> vecp;
#define poi(x,y) make_pair(x,y)
#define sizer (lol) 1e9
#define digss (lol) 9
struct BigNum {
	vecl value;
	void set(lol x) { value = *(new vecl); value.push_back(x); }
	void duplicate(BigNum other) { value = other.value; }
	void add(BigNum other) {
		vecl o = other.value;
		if (o.size() > value.size()) {
			vecl t = value;
			value = o;
			o = t;
		}
		forin(i, o) {
			value[i] += o[i];
			if (i < value.size() - 1 && value[i] >= sizer) {
				value[i + 1] += value[i] / sizer;
				value[i] = value[i] % sizer;
			}
		}
		if (value.back() >= sizer) {
			value.push_back(value.back() / sizer);
			value[value.size() - 2] = value[value.size() - 2] % sizer;
		}
	}
	void mul(lol mul) {
		forin(i, value) {
			value[i] *= mul;
		}
		fori(i, value.size() - 1) {
			if (value[i] >= sizer) {
				value[i + 1] += value[i] / sizer;
				value[i] = value[i] % sizer;
			}
		}
		if (value.back() >= sizer) {
			value.push_back(value.back() / sizer);
			value[value.size() - 2] = value[value.size() - 2] % sizer;
		}
	}
	long double div(BigNum other1, BigNum other2) {
		int s = value.size();
		long double current = value.back();
		if (s >= 2) {
			current += ((long double)value[s - 2]) / sizer;
		}
		if (s >= 3) {
			current += ((long double)value[s - 3]) / (sizer * sizer);
		}
		int s1 = other1.value.size();
		int s2 = other2.value.size();
		long double other = 0;
		if (s1 + s2 - 1 == s) {
			other += other1.value.back() * other2.value.back();
			if (s1 >= 2) {
				other += ((long double)other1.value[s1 - 2] * other2.value.back()) / sizer;
			}
			if (s2 >= 2) {
				other += ((long double)other2.value[s2 - 2] * other1.value.back()) / sizer;
			}
			if (s1 >= 3) {
				other += ((long double)other1.value[s1 - 3] * other2.value.back()) / (sizer * sizer);
			}
			if (s2 >= 3) {
				other += ((long double)other2.value[s2 - 3] * other1.value.back()) / (sizer * sizer);
			}
		}
		if (s1 + s2 - 1 == s - 1) {
			other += other1.value.back() * other2.value.back();
			if (s1 >= 2) {
				other += ((long double)other1.value[s1 - 2] * other2.value.back()) / sizer;
			}
			if (s2 >= 2) {
				other += ((long double)other2.value[s2 - 2] * other1.value.back()) / sizer;
			}
			other /= sizer;
		}
		if (s1 + s2 - 1 == s - 2) {
			other += other1.value.back() * other2.value.back();
			other /= sizer * sizer;
		}
		return other / current;
	}
	string stringify() {
		string out = to_string(value.back());
		forib(i, value.size() - 1) {
			string cur = to_string(value[i] + sizer);
			out += cur.substr(1);
		}
		return out;
	}
};
lol gcd(lol a, lol b) {
	if (b == 0) {
		return a;
	}
	return gcd(b, a % b);
}
lol triangle(lol x) {
	return (((lol)(x + 1)) * (x)) / 2;
}
lol modInverse(lol a)
{
	lol m = maxi;
	lol y = 0, x = 1;
	while (a > 1)
	{
		lol q = a / m;
		lol t = m;
		m = a % m, a = t;
		t = y;
		y = x - q * y;
		x = t;
	}
	if (x < 0) {
		x += maxi;
	}
	return x;
}
lol modInverse(lol a,lol b)
{
	lol m = b;
	lol y = 0, x = 1;
	while (a > 1)
	{
		lol q = a / m;
		lol t = m;
		m = a % m, a = t;
		t = y;
		y = x - q * y;
		x = t;
	}
	if (x < 0) {
		x += b;
	}
	return x;
}
lol pow(lol a, lol b) {
	if (b == 0) {
		return 1;
	}
	if (b % 2 == 0) {
		return pow((a * a)mod, b / 2)mod;
	}
	return (a * pow((a * a)mod, b / 2))mod;
}
vecl dev(vecp divisors) {
	if (divisors.size() == 0) {
		vecl cur;
		cur.push_back(1);
		return cur;
	}
	lol x = divisors.back().first;
	lol n = divisors.back().second;
	divisors.pop_back();
	vecl ans = dev(divisors);
	vecl cur;
	lol xi = 1;
	fori(i, n + 1) {
		forin(j, ans) {
			cur.push_back(ans[j] * xi);
		}
		xi *= x;
	}
	return cur;
}
void add(veci& x, veci& y) {
	forin(i, x) {
		x[i] += y[i];
	}
}
struct pt
{
	lol x, y;

	lol d() const // squared length
	{
		return x * x + y * y;
	}
};
typedef vector<pt> vecpp;
#define intopt(a) into(a.x) into(a.y)

#define defpt(a) pt a;intopt(a)
inline pt operator-(const pt& a) { return { -a.x, -a.y }; }
inline pt operator+(const pt& a, const pt& b) { return { a.x + b.x, a.y + b.y }; }
inline pt operator-(const pt& a, const pt& b) { return { a.x - b.x, a.y - b.y }; }
inline lol operator*(const pt& a, const pt& b) { return a.x* b.y - a.y * b.x; } // cross product
inline lol operator/(const pt& a, const pt& b) { return a.x* b.x + a.y * b.y; } // dot product

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	lol modi = 998244353;
	defm defn
		vector<vecl> x(n+2, vecl(n+2,1));
	vector<vecl> y(m+1, vecl(n + 1, 1));
	vecl a(n+2);
	forn(i, n+1) {
		into(a[i])
		fornb(j, i) {
			if (a[i] == a[j]) {
				fort(k, j, i) {
					y[a[i] - 1][k] = 0;
				}
				br
			}
		}
	}
	forib(j, m) {
		fori(i, n + 1) {
			y[j][i] = min(y[j][i], y[j + 1][i]);
		}
	}
	forn(i, n + 1) {
		if (y[a[i]][i] == 0) {
			co 0 el
			ex
		}
	}
	forn(i, n + 1) {
		fornb(j, i) {
			int p = j;
			fort(pos, j, i + 1) {
				if (a[p] > a[pos]) {
					p = pos;
				}
			}
			lol left = 0;
			fort(l, j-1, p) {
				left = (left + x[j][l] * x[l + 1][p - 1]* y[a[p]][l]) % modi;
			}
			int lp = p;
			fort(pos, j, i + 1) {
				if (a[p] == a[pos]) {
					p = pos;
				}
			}
			lol right = 0;
			fort(r, p, i + 1) {
				right = (right + x[p + 1][r] * x[r + 1][i] * y[a[p]][r]) % modi;
			}
			x[j][i] = (left * right) % modi;
			fort(pos, j, i + 1) {
				if (a[p] == a[pos]) {
					x[j][i] = (x[j][i] * x[lp + 1][pos - 1]) % modi;
					lp = pos;
				}
			}
		}
	}
	co x[1][n] el
		ex
}


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <utility>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <math.h>
#include <iomanip>
using namespace std;
#define forr(i,a,b,c) for(int i=a;i<b;i+=c)
#define forrb(i,a,b,c) for(int i=a;i>b;i-=c)
#define fori(i,n) forr(i,0,n,1)
#define forib(i,n) forrb(i,n-1,-1,1)
#define forn(i,n) forr(i,1,n,1)
#define fornb(i,n) forrb(i,n-1,0,1)
#define fort(i,m,n) forr(i,m,n,1)
#define fortb(i,m,n) forrb(i,n-1,m-1,1)
#define forin(i,arr) fori(i,arr.size())
#define forinb(i,arr) forib(i,arr.size())
#define forrl(i,a,b,c) for(lol i=a;i<b;i+=c)
#define forrbl(i,a,b,c) for(lol i=a;i>b;i-=c)
#define foril(i,n) forrl(i,0,n,1)
#define foribl(i,n) forrbl(i,n-1,-1,1)
#define fornl(i,n) forrl(i,1,n,1)
#define fornbl(i,n) forrbl(i,n-1,0,1)
#define fortl(i,m,n) forrl(i,m,n,1)
#define fortbl(i,m,n) forrbl(i,n-1,m-1,1)
#define forinl(i,arr) foril(i,arr.size())
#define forinbl(i,arr) foribl(i,arr.size())
#define into(i) cin >> i;
#define def(i) lol i; into(i)
#define deft(t,i) t i; into(i)
#define defl(i) lol i; into(i)
#define defs(i) string i; into(i)
#define defn def(n)
#define defp def(p)
#define defm def(m)
#define defk def(k)
#define defa def(a)
#define defb def(b)
#define defc def(c)
#define defd def(d)
#define vec(a) vector<a>
#define co cout <<
#define out(a) cout << a <<' ';
#define el << endl;
#define ell << '\n';
#define outv(arr,n) fori(i,n){out(arr[i])} co "" el
#define cas(p) co "Case #" << p+1 <<": ";
#define ex return 0;
#define qii queue<int>
#define sti stack<int>
#define dei deque<int>
#define con continue;
#define br break;
#define maxi 1000000007
#define lmaxi 100000000000000007
#define mod %maxi
#define wne(arr) while(!arr.empty())
#define all(arr) arr.begin(),arr.end()
typedef vector<int> veci;
typedef long long lol;
typedef unsigned long long ulol;
typedef vector<lol> vecl;
#define table(name,n,m) vector<veci> name(n,veci (m));
#define tablel(name,n,m) vector<vecl> name(n,vecl (m));
typedef pair<lol, lol> point;
typedef pair<point, point> poin;
typedef pair<lol, point> poing;
typedef pair<point, lol> poinf;
typedef vector<point> vecp;
#define poi(x,y) make_pair(x,y)
#define sizer (lol) 1e9
#define digss (lol) 9
struct BigNum {
	vecl value;
	void set(lol x) { value = *(new vecl); value.push_back(x); }
	void duplicate(BigNum other) { value = other.value; }
	void add(BigNum other) {
		vecl o = other.value;
		if (o.size() > value.size()) {
			vecl t = value;
			value = o;
			o = t;
		}
		forin(i, o) {
			value[i] += o[i];
			if (i < value.size() - 1 && value[i] >= sizer) {
				value[i + 1] += value[i] / sizer;
				value[i] = value[i] % sizer;
			}
		}
		if (value.back() >= sizer) {
			value.push_back(value.back() / sizer);
			value[value.size() - 2] = value[value.size() - 2] % sizer;
		}
	}
	void mul(lol mul) {
		forin(i, value) {
			value[i] *= mul;
		}
		fori(i, value.size() - 1) {
			if (value[i] >= sizer) {
				value[i + 1] += value[i] / sizer;
				value[i] = value[i] % sizer;
			}
		}
		if (value.back() >= sizer) {
			value.push_back(value.back() / sizer);
			value[value.size() - 2] = value[value.size() - 2] % sizer;
		}
	}
	long double div(BigNum other1, BigNum other2) {
		int s = value.size();
		long double current = value.back();
		if (s >= 2) {
			current += ((long double)value[s - 2]) / sizer;
		}
		if (s >= 3) {
			current += ((long double)value[s - 3]) / (sizer * sizer);
		}
		int s1 = other1.value.size();
		int s2 = other2.value.size();
		long double other = 0;
		if (s1 + s2 - 1 == s) {
			other += other1.value.back() * other2.value.back();
			if (s1 >= 2) {
				other += ((long double)other1.value[s1 - 2] * other2.value.back()) / sizer;
			}
			if (s2 >= 2) {
				other += ((long double)other2.value[s2 - 2] * other1.value.back()) / sizer;
			}
			if (s1 >= 3) {
				other += ((long double)other1.value[s1 - 3] * other2.value.back()) / (sizer * sizer);
			}
			if (s2 >= 3) {
				other += ((long double)other2.value[s2 - 3] * other1.value.back()) / (sizer * sizer);
			}
		}
		if (s1 + s2 - 1 == s - 1) {
			other += other1.value.back() * other2.value.back();
			if (s1 >= 2) {
				other += ((long double)other1.value[s1 - 2] * other2.value.back()) / sizer;
			}
			if (s2 >= 2) {
				other += ((long double)other2.value[s2 - 2] * other1.value.back()) / sizer;
			}
			other /= sizer;
		}
		if (s1 + s2 - 1 == s - 2) {
			other += other1.value.back() * other2.value.back();
			other /= sizer * sizer;
		}
		return other / current;
	}
	string stringify() {
		string out = to_string(value.back());
		forib(i, value.size() - 1) {
			string cur = to_string(value[i] + sizer);
			out += cur.substr(1);
		}
		return out;
	}
};
lol gcd(lol a, lol b) {
	if (b == 0) {
		return a;
	}
	return gcd(b, a % b);
}
lol triangle(lol x) {
	return (((lol)(x + 1)) * (x)) / 2;
}
lol modInverse(lol a)
{
	lol m = maxi;
	lol y = 0, x = 1;
	while (a > 1)
	{
		lol q = a / m;
		lol t = m;
		m = a % m, a = t;
		t = y;
		y = x - q * y;
		x = t;
	}
	if (x < 0) {
		x += maxi;
	}
	return x;
}
lol modInverse(lol a,lol b)
{
	lol m = b;
	lol y = 0, x = 1;
	while (a > 1)
	{
		lol q = a / m;
		lol t = m;
		m = a % m, a = t;
		t = y;
		y = x - q * y;
		x = t;
	}
	if (x < 0) {
		x += b;
	}
	return x;
}
lol pow(lol a, lol b) {
	if (b == 0) {
		return 1;
	}
	if (b % 2 == 0) {
		return pow((a * a)mod, b / 2)mod;
	}
	return (a * pow((a * a)mod, b / 2))mod;
}
vecl dev(vecp divisors) {
	if (divisors.size() == 0) {
		vecl cur;
		cur.push_back(1);
		return cur;
	}
	lol x = divisors.back().first;
	lol n = divisors.back().second;
	divisors.pop_back();
	vecl ans = dev(divisors);
	vecl cur;
	lol xi = 1;
	fori(i, n + 1) {
		forin(j, ans) {
			cur.push_back(ans[j] * xi);
		}
		xi *= x;
	}
	return cur;
}
void add(veci& x, veci& y) {
	forin(i, x) {
		x[i] += y[i];
	}
}
struct pt
{
	lol x, y;

	lol d() const // squared length
	{
		return x * x + y * y;
	}
};
typedef vector<pt> vecpp;
#define intopt(a) into(a.x) into(a.y)

#define defpt(a) pt a;intopt(a)
inline pt operator-(const pt& a) { return { -a.x, -a.y }; }
inline pt operator+(const pt& a, const pt& b) { return { a.x + b.x, a.y + b.y }; }
inline pt operator-(const pt& a, const pt& b) { return { a.x - b.x, a.y - b.y }; }
inline lol operator*(const pt& a, const pt& b) { return a.x* b.y - a.y * b.x; } // cross product
inline lol operator/(const pt& a, const pt& b) { return a.x* b.x + a.y * b.y; } // dot product

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	lol modi = 998244353;
	defm defn

	vecl aa(n+2);
	forn(i, n+1) {
		into(aa[i])

	}
	veci a;
	fori(i, n + 1) {
		if (aa[i] != aa[i + 1]) {
			a.push_back(aa[i]);
		}
	}
	a.push_back(0);
	n = a.size() - 2;
	vector<vector<char>> y(m + 1, vector<char>(n + 1, 1));
	forn(i, n + 1) {
		fornb(j, i) {
			if (a[i] == a[j]) {
				fort(k, j, i) {
					y[a[i] - 1][k] = 0;
				}
				br
			}
		}
	}
	forib(j, m) {
		fori(i, n + 1) {
			y[j][i] = min(y[j][i], y[j + 1][i]);
		}
	}
	forn(i, n + 1) {
		if (y[a[i]][i] == 0) {
			co 0 el
			ex
		}
	}
	vector<vecl> x(n + 2, vecl(n + 2, 1));
	forn(i, n + 1) {
		fornb(j, i) {
			int p = j;
			fort(pos, j, i + 1) {
				if (a[p] > a[pos]) {
					p = pos;
				}
			}
			lol left = 0;
			fort(l, j-1, p) {
				left = (left + x[j][l] * x[l + 1][p - 1]* y[a[p]][l]) % modi;
			}
			int lp = p;
			fort(pos, j, i + 1) {
				if (a[p] == a[pos]) {
					p = pos;
				}
			}
			lol right = 0;
			fort(r, p, i + 1) {
				right = (right + x[p + 1][r] * x[r + 1][i] * y[a[p]][r]) % modi;
			}
			x[j][i] = (left * right) % modi;
			fort(pos, j, i + 1) {
				if (a[p] == a[pos]) {
					x[j][i] = (x[j][i] * x[lp + 1][pos - 1]) % modi;
					lp = pos;
				}
			}
		}
	}
	co x[1][n] el
		ex
}


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <utility>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <math.h>
#include <iomanip>
using namespace std;
#define forr(i,a,b,c) for(int i=a;i<b;i+=c)
#define forrb(i,a,b,c) for(int i=a;i>b;i-=c)
#define fori(i,n) forr(i,0,n,1)
#define forib(i,n) forrb(i,n-1,-1,1)
#define forn(i,n) forr(i,1,n,1)
#define fornb(i,n) forrb(i,n-1,0,1)
#define fort(i,m,n) forr(i,m,n,1)
#define fortb(i,m,n) forrb(i,n-1,m-1,1)
#define forin(i,arr) fori(i,arr.size())
#define forinb(i,arr) forib(i,arr.size())
#define forrl(i,a,b,c) for(lol i=a;i<b;i+=c)
#define forrbl(i,a,b,c) for(lol i=a;i>b;i-=c)
#define foril(i,n) forrl(i,0,n,1)
#define foribl(i,n) forrbl(i,n-1,-1,1)
#define fornl(i,n) forrl(i,1,n,1)
#define fornbl(i,n) forrbl(i,n-1,0,1)
#define fortl(i,m,n) forrl(i,m,n,1)
#define fortbl(i,m,n) forrbl(i,n-1,m-1,1)
#define forinl(i,arr) foril(i,arr.size())
#define forinbl(i,arr) foribl(i,arr.size())
#define into(i) cin >> i;
#define def(i) lol i; into(i)
#define deft(t,i) t i; into(i)
#define defl(i) lol i; into(i)
#define defs(i) string i; into(i)
#define defn def(n)
#define defp def(p)
#define defm def(m)
#define defk def(k)
#define defa def(a)
#define defb def(b)
#define defc def(c)
#define defd def(d)
#define vec(a) vector<a>
#define co cout <<
#define out(a) cout << a <<' ';
#define el << endl;
#define ell << '\n';
#define outv(arr,n) fori(i,n){out(arr[i])} co "" el
#define cas(p) co "Case #" << p+1 <<": ";
#define ex return 0;
#define qii queue<int>
#define sti stack<int>
#define dei deque<int>
#define con continue;
#define br break;
#define maxi 1000000007
#define lmaxi 100000000000000007
#define mod %maxi
#define wne(arr) while(!arr.empty())
#define all(arr) arr.begin(),arr.end()
typedef vector<int> veci;
typedef long long lol;
typedef unsigned long long ulol;
typedef vector<lol> vecl;
#define table(name,n,m) vector<veci> name(n,veci (m));
#define tablel(name,n,m) vector<vecl> name(n,vecl (m));
typedef pair<lol, lol> point;
typedef pair<point, point> poin;
typedef pair<lol, point> poing;
typedef pair<point, lol> poinf;
typedef vector<point> vecp;
#define poi(x,y) make_pair(x,y)
#define sizer (lol) 1e9
#define digss (lol) 9
struct BigNum {
	vecl value;
	void set(lol x) { value = *(new vecl); value.push_back(x); }
	void duplicate(BigNum other) { value = other.value; }
	void add(BigNum other) {
		vecl o = other.value;
		if (o.size() > value.size()) {
			vecl t = value;
			value = o;
			o = t;
		}
		forin(i, o) {
			value[i] += o[i];
			if (i < value.size() - 1 && value[i] >= sizer) {
				value[i + 1] += value[i] / sizer;
				value[i] = value[i] % sizer;
			}
		}
		if (value.back() >= sizer) {
			value.push_back(value.back() / sizer);
			value[value.size() - 2] = value[value.size() - 2] % sizer;
		}
	}
	void mul(lol mul) {
		forin(i, value) {
			value[i] *= mul;
		}
		fori(i, value.size() - 1) {
			if (value[i] >= sizer) {
				value[i + 1] += value[i] / sizer;
				value[i] = value[i] % sizer;
			}
		}
		if (value.back() >= sizer) {
			value.push_back(value.back() / sizer);
			value[value.size() - 2] = value[value.size() - 2] % sizer;
		}
	}
	long double div(BigNum other1, BigNum other2) {
		int s = value.size();
		long double current = value.back();
		if (s >= 2) {
			current += ((long double)value[s - 2]) / sizer;
		}
		if (s >= 3) {
			current += ((long double)value[s - 3]) / (sizer * sizer);
		}
		int s1 = other1.value.size();
		int s2 = other2.value.size();
		long double other = 0;
		if (s1 + s2 - 1 == s) {
			other += other1.value.back() * other2.value.back();
			if (s1 >= 2) {
				other += ((long double)other1.value[s1 - 2] * other2.value.back()) / sizer;
			}
			if (s2 >= 2) {
				other += ((long double)other2.value[s2 - 2] * other1.value.back()) / sizer;
			}
			if (s1 >= 3) {
				other += ((long double)other1.value[s1 - 3] * other2.value.back()) / (sizer * sizer);
			}
			if (s2 >= 3) {
				other += ((long double)other2.value[s2 - 3] * other1.value.back()) / (sizer * sizer);
			}
		}
		if (s1 + s2 - 1 == s - 1) {
			other += other1.value.back() * other2.value.back();
			if (s1 >= 2) {
				other += ((long double)other1.value[s1 - 2] * other2.value.back()) / sizer;
			}
			if (s2 >= 2) {
				other += ((long double)other2.value[s2 - 2] * other1.value.back()) / sizer;
			}
			other /= sizer;
		}
		if (s1 + s2 - 1 == s - 2) {
			other += other1.value.back() * other2.value.back();
			other /= sizer * sizer;
		}
		return other / current;
	}
	string stringify() {
		string out = to_string(value.back());
		forib(i, value.size() - 1) {
			string cur = to_string(value[i] + sizer);
			out += cur.substr(1);
		}
		return out;
	}
};
lol gcd(lol a, lol b) {
	if (b == 0) {
		return a;
	}
	return gcd(b, a % b);
}
lol triangle(lol x) {
	return (((lol)(x + 1)) * (x)) / 2;
}
lol modInverse(lol a)
{
	lol m = maxi;
	lol y = 0, x = 1;
	while (a > 1)
	{
		lol q = a / m;
		lol t = m;
		m = a % m, a = t;
		t = y;
		y = x - q * y;
		x = t;
	}
	if (x < 0) {
		x += maxi;
	}
	return x;
}
lol modInverse(lol a,lol b)
{
	lol m = b;
	lol y = 0, x = 1;
	while (a > 1)
	{
		lol q = a / m;
		lol t = m;
		m = a % m, a = t;
		t = y;
		y = x - q * y;
		x = t;
	}
	if (x < 0) {
		x += b;
	}
	return x;
}
lol pow(lol a, lol b) {
	if (b == 0) {
		return 1;
	}
	if (b % 2 == 0) {
		return pow((a * a)mod, b / 2)mod;
	}
	return (a * pow((a * a)mod, b / 2))mod;
}
vecl dev(vecp divisors) {
	if (divisors.size() == 0) {
		vecl cur;
		cur.push_back(1);
		return cur;
	}
	lol x = divisors.back().first;
	lol n = divisors.back().second;
	divisors.pop_back();
	vecl ans = dev(divisors);
	vecl cur;
	lol xi = 1;
	fori(i, n + 1) {
		forin(j, ans) {
			cur.push_back(ans[j] * xi);
		}
		xi *= x;
	}
	return cur;
}
void add(veci& x, veci& y) {
	forin(i, x) {
		x[i] += y[i];
	}
}
struct pt
{
	lol x, y;

	lol d() const // squared length
	{
		return x * x + y * y;
	}
};
typedef vector<pt> vecpp;
#define intopt(a) into(a.x) into(a.y)

#define defpt(a) pt a;intopt(a)
inline pt operator-(const pt& a) { return { -a.x, -a.y }; }
inline pt operator+(const pt& a, const pt& b) { return { a.x + b.x, a.y + b.y }; }
inline pt operator-(const pt& a, const pt& b) { return { a.x - b.x, a.y - b.y }; }
inline lol operator*(const pt& a, const pt& b) { return a.x* b.y - a.y * b.x; } // cross product
inline lol operator/(const pt& a, const pt& b) { return a.x* b.x + a.y * b.y; } // dot product

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	lol modi = 998244353;
	defm defn

		vecl aa(n + 2);
	forn(i, n + 1) {
		into(aa[i])

	}
	veci a;
	fori(i, n + 1) {
		if (aa[i] != aa[i + 1]) {
			a.push_back(aa[i]);
		}
	}
	a.push_back(0);
	n = a.size() - 2;
	vector<vecl> x(n + 2, vecl(n + 2, 1));
	vector<vector<char>> y(m + 1, vector<char>(n + 1, 1));
	forn(i, n + 1) {
		fornb(j, i) {
			if (a[i] == a[j]) {
				fort(k, j, i) {
					y[a[i] - 1][k] = 0;
				}
				br
			}
		}
	}
	forib(j, m) {
		fori(i, n + 1) {
			y[j][i] = min(y[j][i], y[j + 1][i]);
		}
	}
	forn(i, n + 1) {
		if (y[a[i]][i] == 0) {
			co 0 el
				ex
		}
	}
	forn(i, n + 1) {
		fornb(j, i) {
			int p = j;
			fort(pos, j, i + 1) {
				if (a[p] > a[pos]) {
					p = pos;
				}
			}
			lol left = 0;
			fort(l, j - 1, p) {
				left = (left + x[j][l] * x[l + 1][p - 1] * y[a[p]][l]) % modi;
			}
			int lp = p;
			fort(pos, j, i + 1) {
				if (a[p] == a[pos]) {
					p = pos;
				}
			}
			lol right = 0;
			fort(r, p, i + 1) {
				right = (right + x[p + 1][r] * x[r + 1][i] * y[a[p]][r]) % modi;
			}
			x[j][i] = (left * right) % modi;
			fort(pos, j, i + 1) {
				if (a[p] == a[pos]) {
					x[j][i] = (x[j][i] * x[lp + 1][pos - 1]) % modi;
					lp = pos;
				}
			}
		}
	}
	co x[1][n] el
		ex
}


#include <bits/stdc++.h>
using namespace std;
const int kN = 505;
const int kMod = 998244353;
int p[kN], pos[kN];
int low[kN][kN];
int dp[kN][kN];
bool vis[kN][kN];
void add(int &a, int b) {
	a += b;
	if(a >= kMod) a -= kMod;
}
int dfs(int l, int r) {
	if(l == r) return 1;
	if(vis[l][r]) return dp[l][r];
	vis[l][r] = 1;
	int le = 0, ri = 0;
	int x = pos[low[l][r]];
	//printf("l = %d, r = %d, x = %d\n", l, r, x);
	for(int i = l; i <= x; i++) add(le, 1LL * dfs(l, i) * dfs(i, x) % kMod);
	for(int i = x + 1; i <= r; i++) add(ri, 1LL * dfs(x + 1, i) * dfs(i, r) % kMod);
	//printf("dp[%d][%d] = %d, le = %d, ri = %d\n", l, r, 1LL * le * ri % kMod, le, ri);
	return dp[l][r] = 1LL * le * ri % kMod;
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 0; i < n; i++) scanf("%d", p + i), p[i]--;
	for(int i = 0; i < n; i++) pos[p[i]] = i;
	for(int i = 0; i < n; i++) {
		int mn = n + 1;
		for(int j = i; j < n; j++) {
			mn = min(mn, p[j]);
			low[i][j + 1] = mn;
		}
	}
	printf("%d\n", dfs(0, n));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int kN = 1510;
const int kMod = 998244353;
const int kInf = 1e9;
int p[kN], q[kN];
vector<int> pos[kN];
int low[kN][kN];
int dp[kN][kN];
bool vis[kN][kN];
void add(int &a, int b) {
	a += b;
	if(a >= kMod) a -= kMod;
}
int dfs(int l, int r) {
	if(l == r) return 1;
	if(vis[l][r]) return dp[l][r];
	vis[l][r] = 1;
	int le = 0, ri = 0;
	int c = low[l][r];
	int x_mn = pos[c][0], x_mx = pos[c].back();
	if(x_mn < l || x_mx >= r) return dp[l][r] = 0;
	//printf("l = %d, r = %d, x = %d\n", l, r, x);
	for(int i = l; i <= x_mn; i++) add(le, 1LL * dfs(l, i) * dfs(i, x_mn) % kMod);
	for(int i = x_mx + 1; i <= r; i++) add(ri, 1LL * dfs(x_mx + 1, i) * dfs(i, r) % kMod);
	dp[l][r] = 1LL * le * ri % kMod;
	for(int i = 0; i < int(pos[c].size()) - 1; i++)
		dp[l][r] = 1LL * dp[l][r] * dfs(pos[c][i] + 1, pos[c][i + 1]) % kMod;
	//printf("dp[%d][%d] = %d, le = %d, ri = %d\n", l, r, 1LL * le * ri % kMod, le, ri);
	return dp[l][r];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i++) scanf("%d", p + i), p[i]--;
	int M = 0;
	for(int i = 0; i < m; i++)
		if(M == 0 || p[i] != q[M - 1]) q[M++] = p[i];
	m = M;
	if(m >= 2 * n + 10) return puts("0"), 0;
	for(int i = 0; i < m; i++) pos[q[i]].push_back(i);
	for(int i = 0; i < m; i++) {
		int mn = kInf;
		for(int j = i; j < m; j++) {
			mn = min(mn, q[j]);
			low[i][j + 1] = mn;
		}
	}
	printf("%d\n", dfs(0, m));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int kN = 1510;
const int kMod = 998244353;
const int kInf = 1e9;
int p[kN], q[kN];
vector<int> pos[kN];
int low[kN][kN];
int dp[kN][kN];
bool vis[kN][kN];
void add(int &a, int b) {
	a += b;
	if(a >= kMod) a -= kMod;
}
int dfs(int l, int r) {
	if(l == r) return 1;
	if(vis[l][r]) return dp[l][r];
	vis[l][r] = 1;
	int le = 0, ri = 0;
	int c = low[l][r];
	int x_mn = pos[c][0], x_mx = pos[c].back();
	if(x_mn < l || x_mx >= r) return dp[l][r] = 0;
	//printf("l = %d, r = %d, x = %d\n", l, r, x);
	for(int i = l; i <= x_mn; i++) add(le, 1LL * dfs(l, i) * dfs(i, x_mn) % kMod);
	for(int i = x_mx + 1; i <= r; i++) add(ri, 1LL * dfs(x_mx + 1, i) * dfs(i, r) % kMod);
	dp[l][r] = 1LL * le * ri % kMod;
	for(int i = 0; i < int(pos[c].size()) - 1; i++)
		dp[l][r] = 1LL * dp[l][r] * dfs(pos[c][i] + 1, pos[c][i + 1]) % kMod;
	//printf("dp[%d][%d] = %d, le = %d, ri = %d\n", l, r, 1LL * le * ri % kMod, le, ri);
	return dp[l][r];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i++) scanf("%d", p + i), p[i]--;
	int M = 0;
	for(int i = 0; i < m; i++) {
		if(M == 0 || p[i] != q[M - 1]) q[M++] = p[i];
		if(M >= 2 * n + 10) break;
	}
	m = M;
	if(m >= 2 * n + 10) return puts("0"), 0;
	for(int i = 0; i < m; i++) pos[q[i]].push_back(i);
	for(int i = 0; i < m; i++) {
		int mn = kInf;
		for(int j = i; j < m; j++) {
			mn = min(mn, q[j]);
			low[i][j + 1] = mn;
		}
	}
	printf("%d\n", dfs(0, m));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int kN = 1510;
const int kM = 1e6 + 10;
const int kMod = 998244353;
const int kInf = 1e9;
int p[kM], q[kM];
vector<int> pos[kN];
int low[kN][kN];
int dp[kN][kN];
bool vis[kN][kN];
void add(int &a, int b) {
	a += b;
	if(a >= kMod) a -= kMod;
}
int dfs(int l, int r) {
	if(l == r) return 1;
	if(vis[l][r]) return dp[l][r];
	vis[l][r] = 1;
	int le = 0, ri = 0;
	int c = low[l][r];
	int x_mn = pos[c][0], x_mx = pos[c].back();
	if(x_mn < l || x_mx >= r) return dp[l][r] = 0;
	//printf("l = %d, r = %d, x = %d\n", l, r, x);
	for(int i = l; i <= x_mn; i++) add(le, 1LL * dfs(l, i) * dfs(i, x_mn) % kMod);
	for(int i = x_mx + 1; i <= r; i++) add(ri, 1LL * dfs(x_mx + 1, i) * dfs(i, r) % kMod);
	dp[l][r] = 1LL * le * ri % kMod;
	for(int i = 0; i < int(pos[c].size()) - 1; i++)
		dp[l][r] = 1LL * dp[l][r] * dfs(pos[c][i] + 1, pos[c][i + 1]) % kMod;
	//printf("dp[%d][%d] = %d, le = %d, ri = %d\n", l, r, 1LL * le * ri % kMod, le, ri);
	return dp[l][r];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i++) scanf("%d", p + i), p[i]--;
	int M = 0;
	for(int i = 0; i < m; i++) {
		if(M == 0 || p[i] != q[M - 1]) q[M++] = p[i];
		if(M >= 2 * n + 10) break;
	}
	m = M;
	if(m >= 2 * n + 10) return puts("0"), 0;
	for(int i = 0; i < m; i++) pos[q[i]].push_back(i);
	for(int i = 0; i < m; i++) {
		int mn = kInf;
		for(int j = i; j < m; j++) {
			mn = min(mn, q[j]);
			low[i][j + 1] = mn;
		}
	}
	printf("%d\n", dfs(0, m));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int kN = 1010;
const int kMod = 998244353;
const int kInf = 1e9;
int p[kN], q[kN];
vector<int> pos[kN];
int low[kN][kN];
int dp[kN][kN];
bool vis[kN][kN];
void add(int &a, int b) {
	a += b;
	if(a >= kMod) a -= kMod;
}
int dfs(int l, int r) {
	if(l == r) return 1;
	if(vis[l][r]) return dp[l][r];
	vis[l][r] = 1;
	int le = 0, ri = 0;
	int c = low[l][r];
	int x_mn = pos[c][0], x_mx = pos[c].back();
	if(x_mn < l || x_mx >= r) return dp[l][r] = 0;
	//printf("l = %d, r = %d, x = %d\n", l, r, x);
	for(int i = l; i <= x_mn; i++) add(le, 1LL * dfs(l, i) * dfs(i, x_mn) % kMod);
	for(int i = x_mx + 1; i <= r; i++) add(ri, 1LL * dfs(x_mx + 1, i) * dfs(i, r) % kMod);
	dp[l][r] = 1LL * le * ri % kMod;
	for(int i = 0; i < int(pos[c].size()) - 1; i++)
		dp[l][r] = 1LL * dp[l][r] * dfs(pos[c][i] + 1, pos[c][i + 1]) % kMod;
	//printf("dp[%d][%d] = %d, le = %d, ri = %d\n", l, r, 1LL * le * ri % kMod, le, ri);
	return dp[l][r];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i++) scanf("%d", p + i), p[i]--;
	int M = 0;
	for(int i = 0; i < m; i++)
		if(M == 0 || p[i] != q[M - 1]) q[M++] = p[i];
	m = M;
	if(m >= 2 * n + 10) return puts("0"), 0;
	for(int i = 0; i < m; i++) pos[q[i]].push_back(i);
	for(int i = 0; i < m; i++) {
		int mn = kInf;
		for(int j = i; j < m; j++) {
			mn = min(mn, q[j]);
			low[i][j + 1] = mn;
		}
	}
	printf("%d\n", dfs(0, m));
	return 0;
}


#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=1000+100,M=1000000+100;
const db pi=acos(-1.0);
#define lowbit(x) ((x)&(-x))
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

inline ll readll()
{
    ll x=0;int f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

namespace My_Math{
    #define N 100000

    int fac[N+100],invfac[N+100];

    int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    int mul(int x,int y) {return 1ll*x*y%maxd;}
    ll qpow(ll x,int y)
    {
        ll ans=1;
        while (y)
        {
            if (y&1) ans=mul(ans,x);
            x=mul(x,x);y>>=1;
        }
        return ans;
    }
    int getinv(int x) {return qpow(x,maxd-2);}

    int C(int n,int m)
    {
        if ((n<m) || (n<0) || (m<0)) return 0;
        return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    }

    void math_init()
    {
        fac[0]=invfac[0]=1;
        rep(i,1,N) fac[i]=mul(fac[i-1],i);
        invfac[N]=getinv(fac[N]);
        per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    }
    #undef N
}
using namespace My_Math;

int n,m,a[M],b[M],k,pos[N],nxt[N],L[N],R[N],f[N][N];

int main()
{
    n=read();m=read();
    rep(i,1,m) a[i]=read();
    rep(i,1,m) if (a[i]!=a[i-1]) b[++k]=a[i];
    if (k>n*2) {puts("0");return 0;}
    rep(i,1,k) a[i]=b[i];m=k;
    rep(i,1,n) pos[i]=m+1;
    per(i,m,1)
    {
        nxt[i]=pos[a[i]];
        pos[a[i]]=i;
    }
    rep(i,1,m)
    {
        if (!L[a[i]]) L[a[i]]=i;
        R[a[i]]=i;
    }
    rep(i,0,m+1) rep(j,0,m+1)
        if (i>j) f[i][j]=1;
    rep(i,1,m)
    {
        if ((L[a[i]]==i) && (R[a[i]]==i)) f[i][i]=1;
    }
    rep(len,2,m)
    {
        rep(l,1,m-len+1)
        {
            int r=l+len-1,pos=0,mn=maxd;
            rep(i,l,r) mn=min(a[i],mn);
            if ((L[mn]<l) || (R[mn]>r)) continue;
            int s1=0,s2=0;
            rep(i,l,L[mn]) s1=add(s1,mul(f[l][i-1],f[i][L[mn]-1]));
            rep(i,R[mn],r) s2=add(s2,mul(f[R[mn]+1][i],f[i+1][r]));
            int s=1;
            for (int i=L[mn];i!=R[mn];i=nxt[i])
                s=mul(s,f[i+1][nxt[i]-1]);
            f[l][r]=mul(mul(s1,s2),s);
        }
    }
    printf("%d",f[1][m]);
    return 0;
}


#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=1000+100;
const db pi=acos(-1.0);
#define lowbit(x) ((x)&(-x))
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

inline ll readll()
{
    ll x=0;int f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

namespace My_Math{
    #define N 100000

    int fac[N+100],invfac[N+100];

    int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    int mul(int x,int y) {return 1ll*x*y%maxd;}
    ll qpow(ll x,int y)
    {
        ll ans=1;
        while (y)
        {
            if (y&1) ans=mul(ans,x);
            x=mul(x,x);y>>=1;
        }
        return ans;
    }
    int getinv(int x) {return qpow(x,maxd-2);}

    int C(int n,int m)
    {
        if ((n<m) || (n<0) || (m<0)) return 0;
        return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    }

    void math_init()
    {
        fac[0]=invfac[0]=1;
        rep(i,1,N) fac[i]=mul(fac[i-1],i);
        invfac[N]=getinv(fac[N]);
        per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    }
    #undef N
}
using namespace My_Math;

int n,m,a[N],b[N],k,pos[N],nxt[N],L[N],R[N],f[N][N];

int main()
{
    n=read();m=read();
    rep(i,1,m) a[i]=read();
    rep(i,1,m) if (a[i]!=a[i-1]) b[++k]=a[i];
    if (k>n*2) {puts("0");return 0;}
    rep(i,1,k) a[i]=b[i];m=k;
    rep(i,1,n) pos[i]=m+1;
    per(i,m,1)
    {
        nxt[i]=pos[a[i]];
        pos[a[i]]=i;
    }
    rep(i,1,m)
    {
        if (!L[a[i]]) L[a[i]]=i;
        R[a[i]]=i;
    }
    rep(i,0,m+1) rep(j,0,m+1)
        if (i>j) f[i][j]=1;
    rep(i,1,m)
    {
        if ((L[a[i]]==i) && (R[a[i]]==i)) f[i][i]=1;
    }
    rep(len,2,m)
    {
        rep(l,1,m-len+1)
        {
            int r=l+len-1,pos=0,mn=maxd;
            rep(i,l,r) mn=min(a[i],mn);
            if ((L[mn]<l) || (R[mn]>r)) continue;
            int s1=0,s2=0;
            rep(i,l,L[mn]) s1=add(s1,mul(f[l][i-1],f[i][L[mn]-1]));
            rep(i,R[mn],r) s2=add(s2,mul(f[R[mn]+1][i],f[i+1][r]));
            int s=1;
            for (int i=L[mn];i!=R[mn];i=nxt[i])
                s=mul(s,f[i+1][nxt[i]-1]);
            f[l][r]=mul(mul(s1,s2),s);
        }
    }
    printf("%d",f[1][m]);
    return 0;
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int MOD = 998244353;
const ll INF = 1e18;
const int MX = 100001; //check the limits, dummy

ll SZ = 262144*4;
ll* seg = new ll[2*SZ]; //segtree implementation by bqi343's Github

ll combine(ll a, ll b) { return min(a, b); }

void build() { F0Rd(i,SZ) seg[i] = combine(seg[2*i],seg[2*i+1]); }

void update(int p, ll value) {
    for (seg[p += SZ] = value; p > 1; p >>= 1)
        seg[p>>1] = combine(seg[(p|1)^1], seg[p|1]);
}

ll query(int l, int r) {  // sum on interval [l, r]
    ll resL = 10000, resR = 10000; r++;
    for (l += SZ, r += SZ; l < r; l >>= 1, r >>= 1) {
        if (l&1) resL = combine(resL,seg[l++]);
        if (r&1) resR = combine(seg[--r],resR);
    }
    return combine(resL,resR);
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);

    int N, M; cin >> N >> M;
    int data[M]; F0R(i, M) cin >> data[i];

    int first[N], last[N];
    F0R(i, N) first[i] = -1;

    F0R(i, M) {
        data[i]--;
        if (first[data[i]] == -1) {
            first[data[i]] = i;
        }
        last[data[i]] = i;
    }

    stack<int> curStack;
    F0R(i, M) {
        if (i == first[data[i]]) {
            if (!curStack.empty() && curStack.top() > data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.push(data[i]);
        }
        if (curStack.top() > data[i]) {
            cout << 0 << endl; return 0;
        }
        if (i == last[data[i]]) {
            if (curStack.empty() || curStack.top() != data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.pop();
        }
    }

    F0R(i, 2*SZ) {
        seg[i] = 100000;
    }
    F0R(i, M) {
        update(i, data[i]);
    }
    vector<vi> pos(N);
    F0R(i, M) {
        pos[data[i]].pb(i);
    }
    bool isRange[N][N];
    vector<pair<int, pi> > ranges;
    int nxtVal[N][N];
    F0R(i, N) {
        F0R(j, N) {
            auto it = lower_bound(all(pos[j]), first[i]);
            if (it == pos[j].end()) {
                nxtVal[i][j] = M+1;
            } else {
                nxtVal[i][j] = *it;
            }
        }
    }
    F0R(i, N) {
        F0R(j, N) {
            bool good = true;
            if (first[i] > first[j] || last[i] > last[j]) good = false;
            F0R(k, N) {
                if (!(last[k] < first[i] || last[j] < first[k] || (first[i] <= first[k] && last[k] <= last[j]) || (first[k] < first[i] && last[j] < last[k]))) {
                    good = false;
                }
                if (nxtVal[i][k] < last[j] && (first[k] < first[i] || last[k] > last[j])) {
                    //cout << i << " " << j << " bad with " << k << endl;
                    good = false;
                }
            }
            //if something contained in this range is also outside of it?

            isRange[i][j] = good;
            if (good) {
                ranges.pb({last[j]-first[i], {i, j}});
            }
        }
    }

    ll inner[N]; F0R(i, N) inner[i] = -1;
    ll dp[N][N];

    sort(all(ranges));
    F0R(index, sz(ranges)) {
        pi range = ranges[index].s;
        int beg = range.f, end = range.s;
        //cout << beg << " " << end << endl;
        int mindex = query(first[beg], last[end]);
        if (beg == mindex && end == mindex) {
            //compute inner product
            ll ans = 1;
            F0R(i, sz(pos[beg]) - 1) {
                int bInd = pos[beg][i];
                int eInd = pos[beg][i+1];
                if (bInd == eInd-1) continue;
                bInd = data[bInd+1];
                eInd = data[eInd-1];
                ans *= dp[bInd][eInd];
            }
            dp[beg][end] = ans;
            inner[beg] = ans;
        } else {
            ll ans = inner[mindex];
            ll begSum = 0, endSum = 0;
            int minB = first[mindex], maxB = last[mindex];
            if (beg == mindex) {
                begSum = 1;
            } else {
                begSum = dp[beg][data[minB-1]]*2;
            }
            if (end == mindex) {
                endSum = 1;

            } else {
                endSum = dp[data[maxB+1]][end]*2;
            }

            F0R(i, N) {
                if (i == beg || i == end) continue;
                if (first[i] > first[beg] && last[i] < first[mindex]) {
                    if(isRange[beg][data[first[i]-1]] && isRange[i][data[first[mindex]-1]]) {
                        begSum += dp[beg][data[first[i] - 1]] * dp[i][data[first[mindex]-1]];
                    }
                    begSum %= MOD;
                }
                if (first[i] > last[mindex] && last[i] < last[end]) {
                    if (isRange[data[last[mindex]+1]][i] && isRange[data[last[i]+1]][end]) {
                        endSum += dp[data[last[mindex]+1]][i] * dp[data[last[i]+1]][end];
                    }
                    endSum %= MOD;
                }
            }
            ans *= begSum; ans %= MOD;
            ans *= endSum; ans %= MOD;
            dp[beg][end] = ans;
        }
    }

    F0R(i, N) {
        F0R(j, N) {
            //if (isRange[i][j]) cout << i << " " << j << " " << dp[i][j] << endl;
        }
    }

    cout << dp[data[0]][data[M-1]] << endl;

	return 0;
}

// read the question correctly (ll vs int)
// template by bqi343


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int MOD = 998244353;
const ll INF = 1e18;
const int MX = 100001; //check the limits, dummy

ll SZ = 262144*4;
ll* seg = new ll[2*SZ]; //segtree implementation by bqi343's Github

ll combine(ll a, ll b) { return min(a, b); }

void build() { F0Rd(i,SZ) seg[i] = combine(seg[2*i],seg[2*i+1]); }

void update(int p, ll value) {
    for (seg[p += SZ] = value; p > 1; p >>= 1)
        seg[p>>1] = combine(seg[(p|1)^1], seg[p|1]);
}

ll query(int l, int r) {  // sum on interval [l, r]
    ll resL = 10000, resR = 10000; r++;
    for (l += SZ, r += SZ; l < r; l >>= 1, r >>= 1) {
        if (l&1) resL = combine(resL,seg[l++]);
        if (r&1) resR = combine(seg[--r],resR);
    }
    return combine(resL,resR);
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);

    int N, M; cin >> N >> M;
    int data[M]; F0R(i, M) cin >> data[i];

    int first[N], last[N];
    F0R(i, N) first[i] = -1;

    F0R(i, M) {
        data[i]--;
        if (first[data[i]] == -1) {
            first[data[i]] = i;
        }
        last[data[i]] = i;
    }

    stack<int> curStack;
    F0R(i, M) {
        if (i == first[data[i]]) {
            if (!curStack.empty() && curStack.top() > data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.push(data[i]);
        }
        if (curStack.top() > data[i]) {
            cout << 0 << endl; return 0;
        }
        if (i == last[data[i]]) {
            if (curStack.empty() || curStack.top() != data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.pop();
        }
    }

    F0R(i, 2*SZ) {
        seg[i] = 100000;
    }
    F0R(i, M) {
        update(i, data[i]);
    }
    vector<vi> pos(N);
    F0R(i, M) {
        pos[data[i]].pb(i);
    }
    bool isRange[N][N];
    vector<pair<int, pi> > ranges;
    int nxtVal[N][N];
    F0R(i, N) {
        F0R(j, N) {
            auto it = lower_bound(all(pos[j]), first[i]);
            if (it == pos[j].end()) {
                nxtVal[i][j] = M+1;
            } else {
                nxtVal[i][j] = *it;
            }
        }
    }
    F0R(i, N) {
        F0R(j, N) {
            bool good = true;
            if (first[i] > first[j] || last[i] > last[j]) good = false;
            F0R(k, N) {
                if (!(last[k] < first[i] || last[j] < first[k] || (first[i] <= first[k] && last[k] <= last[j]) || (first[k] < first[i] && last[j] < last[k]))) {
                    good = false;
                }
                if (nxtVal[i][k] < last[j] && (first[k] < first[i] || last[k] > last[j])) {
                    //cout << i << " " << j << " bad with " << k << endl;
                    good = false;
                }
            }
            //if something contained in this range is also outside of it?

            isRange[i][j] = good;
            if (good) {
                ranges.pb({last[j]-first[i], {i, j}});
            }
        }
    }

    ll inner[N]; F0R(i, N) inner[i] = -1;
    ll dp[N][N];

    sort(all(ranges));
    F0R(index, sz(ranges)) {
        pi range = ranges[index].s;
        int beg = range.f, end = range.s;
        //cout << beg << " " << end << endl;
        int mindex = query(first[beg], last[end]);
        if (beg == mindex && end == mindex) {
            //compute inner product
            ll ans = 1;
            F0R(i, sz(pos[beg]) - 1) {
                int bInd = pos[beg][i];
                int eInd = pos[beg][i+1];
                if (bInd == eInd-1) continue;
                bInd = data[bInd+1];
                eInd = data[eInd-1];
                ans *= dp[bInd][eInd];
                ans %= MOD;
            }
            dp[beg][end] = ans;
            inner[beg] = ans;
        } else {
            ll ans = inner[mindex];
            ll begSum = 0, endSum = 0;
            int minB = first[mindex], maxB = last[mindex];
            if (beg == mindex) {
                begSum = 1;
            } else {
                begSum = dp[beg][data[minB-1]]*2;
            }
            if (end == mindex) {
                endSum = 1;

            } else {
                endSum = dp[data[maxB+1]][end]*2;
            }

            F0R(i, N) {
                if (i == beg || i == end) continue;
                if (first[i] > first[beg] && last[i] < first[mindex]) {
                    if(isRange[beg][data[first[i]-1]] && isRange[i][data[first[mindex]-1]]) {
                        begSum += dp[beg][data[first[i] - 1]] * dp[i][data[first[mindex]-1]];
                    }
                    begSum %= MOD;
                }
                if (first[i] > last[mindex] && last[i] < last[end]) {
                    if (isRange[data[last[mindex]+1]][i] && isRange[data[last[i]+1]][end]) {
                        endSum += dp[data[last[mindex]+1]][i] * dp[data[last[i]+1]][end];
                    }
                    endSum %= MOD;
                }
            }
            ans *= begSum; ans %= MOD;
            ans *= endSum; ans %= MOD;
            dp[beg][end] = ans;
        }
    }

    F0R(i, N) {
        F0R(j, N) {
            //if (isRange[i][j]) cout << i << " " << j << " " << dp[i][j] << endl;
        }
    }

    cout << dp[data[0]][data[M-1]] << endl;

	return 0;
}

// read the question correctly (ll vs int)
// template by bqi343


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int MOD = 998244353;
const ll INF = 1e18;
const int MX = 100001; //check the limits, dummy

ll SZ = 262144*4;
ll* seg = new ll[2*SZ]; //segtree implementation by bqi343's Github

ll combine(ll a, ll b) { return min(a, b); }

void build() { F0Rd(i,SZ) seg[i] = combine(seg[2*i],seg[2*i+1]); }

void update(int p, ll value) {
    for (seg[p += SZ] = value; p > 1; p >>= 1)
        seg[p>>1] = combine(seg[(p|1)^1], seg[p|1]);
}

ll query(int l, int r) {  // sum on interval [l, r]
    ll resL = 10000, resR = 10000; r++;
    for (l += SZ, r += SZ; l < r; l >>= 1, r >>= 1) {
        if (l&1) resL = combine(resL,seg[l++]);
        if (r&1) resR = combine(seg[--r],resR);
    }
    return combine(resL,resR);
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);

    int N, M; cin >> N >> M;
    int data[M]; F0R(i, M) cin >> data[i];

    int first[N], last[N];
    F0R(i, N) first[i] = -1;

    F0R(i, M) {
        data[i]--;
        if (first[data[i]] == -1) {
            first[data[i]] = i;
        }
        last[data[i]] = i;
    }

    stack<int> curStack;
    F0R(i, M) {
        if (i == first[data[i]]) {
            if (!curStack.empty() && curStack.top() > data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.push(data[i]);
        }
        if (curStack.top() > data[i]) {
            cout << 0 << endl; return 0;
        }
        if (i == last[data[i]]) {
            if (curStack.empty() || curStack.top() != data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.pop();
        }
    }

    F0R(i, 2*SZ) {
        seg[i] = 100000;
    }
    F0R(i, M) {
        update(i, data[i]);
    }

    bool isRange[N][N];
    vector<pair<int, pi> > ranges;
    F0R(i, N) {
        F0R(j, N) {
            bool good = true;
            if (first[i] > first[j] || last[i] > last[j]) good = false;
            F0R(k, N) {
                if (!(last[k] < first[i] || last[j] < first[k] || (first[i] <= first[k] && last[k] <= last[j]) || (first[k] < first[i] && last[j] < last[k]))) {
                    good = false;
                }
            }
            isRange[i][j] = good;
            if (good) {
                ranges.pb({last[j]-first[i], {i, j}});
            }
        }
    }

    vector<vi> pos(N);
    F0R(i, M) {
        pos[data[i]].pb(i);
    }

    ll inner[N]; F0R(i, N) inner[i] = -1;
    ll dp[N][N];

    sort(all(ranges));
    F0R(index, sz(ranges)) {
        pi range = ranges[index].s;
        int beg = range.f, end = range.s;
        //cout << beg << " " << end << endl;
        int mindex = query(first[beg], last[end]);
        if (beg == mindex && end == mindex) {
            //compute inner product
            ll ans = 1;
            F0R(i, sz(pos[beg]) - 1) {
                int bInd = pos[beg][i];
                int eInd = pos[beg][i+1];
                if (bInd == eInd-1) continue;
                bInd = data[bInd+1];
                eInd = data[eInd-1];
                ans *= dp[bInd][eInd];
            }
            dp[beg][end] = ans;
            inner[beg] = ans;
        } else {
            ll ans = inner[mindex];
            ll begSum = 0, endSum = 0;
            int minB = first[mindex], maxB = last[mindex];
            if (beg == mindex) {
                begSum = 1;
            } else {
                begSum = dp[beg][data[minB-1]]*2;
            }
            if (end == mindex) {
                endSum = 1;

            } else {
                endSum = dp[data[maxB+1]][end]*2;
            }

            F0R(i, N) {
                if (i == beg || i == end) continue;
                if (first[i] > first[beg] && last[i] < first[mindex]) {
                    if(isRange[beg][data[first[i]-1]] && isRange[i][data[first[mindex]-1]]) {
                        begSum += dp[beg][data[first[i] - 1]] * dp[i][data[first[mindex]-1]];
                    }
                    begSum %= MOD;
                }
                if (first[i] > last[mindex] && last[i] < last[end]) {
                    if (isRange[data[last[mindex]+1]][i] && isRange[data[last[i]+1]][end]) {
                        endSum += dp[data[last[mindex]+1]][i] * dp[data[last[i]+1]][end];
                    }
                    endSum %= MOD;
                }
            }
            ans *= begSum; ans %= MOD;
            ans *= endSum; ans %= MOD;
            dp[beg][end] = ans;
        }
    }

    F0R(i, N) {
        F0R(j, N) {
            //if (isRange[i][j]) cout << i << " " << j << " " << dp[i][j] << endl;
        }
    }

    cout << dp[data[0]][data[M-1]] << endl;

	return 0;
}

// read the question correctly (ll vs int)
// template by bqi343


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int MOD = 998244353;
const ll INF = 1e18;
const int MX = 100001; //check the limits, dummy

ll SZ = 262144*4;
ll* seg = new ll[2*SZ]; //segtree implementation by bqi343's Github

ll combine(ll a, ll b) { return min(a, b); }

void build() { F0Rd(i,SZ) seg[i] = combine(seg[2*i],seg[2*i+1]); }

void update(int p, ll value) {
    for (seg[p += SZ] = value; p > 1; p >>= 1)
        seg[p>>1] = combine(seg[(p|1)^1], seg[p|1]);
}

ll query(int l, int r) {  // sum on interval [l, r]
    ll resL = 10000, resR = 10000; r++;
    for (l += SZ, r += SZ; l < r; l >>= 1, r >>= 1) {
        if (l&1) resL = combine(resL,seg[l++]);
        if (r&1) resR = combine(seg[--r],resR);
    }
    return combine(resL,resR);
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);

    int N, M; cin >> N >> M;
    int data[M]; F0R(i, M) cin >> data[i];

    int first[N], last[N];
    F0R(i, N) first[i] = -1;

    F0R(i, M) {
        data[i]--;
        if (first[data[i]] == -1) {
            first[data[i]] = i;
        }
        last[data[i]] = i;
    }

    stack<int> curStack;
    F0R(i, M) {
        if (i == first[data[i]]) {
            if (!curStack.empty() && curStack.top() > data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.push(data[i]);
        }
        if (i == last[data[i]]) {
            if (curStack.empty() || curStack.top() != data[i]) {
                cout << 0 << endl; return 0;
            }
            curStack.pop();
        }
    }

    F0R(i, 2*SZ) {
        seg[i] = 100000;
    }
    F0R(i, M) {
        update(i, data[i]);
    }

    bool isRange[N][N];
    vector<pair<int, pi> > ranges;
    F0R(i, N) {
        F0R(j, N) {
            bool good = true;
            if (first[i] > first[j] || last[i] > last[j]) good = false;
            F0R(k, N) {
                if (!(last[k] < first[i] || last[j] < first[k] || (first[i] <= first[k] && last[k] <= last[j]) || (first[k] < first[i] && last[j] < last[k]))) {
                    good = false;
                }
            }
            isRange[i][j] = good;
            if (good) {
                ranges.pb({last[j]-first[i], {i, j}});
            }
        }
    }

    vector<vi> pos(N);
    F0R(i, M) {
        pos[data[i]].pb(i);
    }

    ll inner[N]; F0R(i, N) inner[i] = -1;
    ll dp[N][N];

    sort(all(ranges));
    F0R(index, sz(ranges)) {
        pi range = ranges[index].s;
        int beg = range.f, end = range.s;
        //cout << beg << " " << end << endl;
        int mindex = query(first[beg], last[end]);
        if (beg == mindex && end == mindex) {
            //compute inner product
            ll ans = 1;
            F0R(i, sz(pos[beg]) - 1) {
                int bInd = pos[beg][i];
                int eInd = pos[beg][i+1];
                if (bInd == eInd-1) continue;
                bInd = data[bInd+1];
                eInd = data[eInd-1];
                ans *= dp[bInd][eInd];
            }
            dp[beg][end] = ans;
            inner[beg] = ans;
        } else {
            ll ans = inner[mindex];
            ll begSum = 0, endSum = 0;
            int minB = first[mindex], maxB = last[mindex];
            if (beg == mindex) {
                begSum = 1;
            } else {
                begSum = dp[beg][data[minB-1]]*2;
            }
            if (end == mindex) {
                endSum = 1;

            } else {
                endSum = dp[data[maxB+1]][end]*2;
            }

            F0R(i, N) {
                if (i == beg || i == end) continue;
                if (first[i] > first[beg] && last[i] < first[mindex]) {
                    if(isRange[beg][data[first[i]-1]] && isRange[i][data[first[mindex]-1]]) {
                        begSum += dp[beg][data[first[i] - 1]] * dp[i][data[first[mindex]-1]];
                    }
                    begSum %= MOD;
                }
                if (first[i] > last[mindex] && last[i] < last[end]) {
                    if (isRange[data[last[mindex]+1]][i] && isRange[data[last[i]+1]][end]) {
                        endSum += dp[data[last[mindex]+1]][i] * dp[data[last[i]+1]][end];
                    }
                    endSum %= MOD;
                }
            }
            ans *= begSum; ans %= MOD;
            ans *= endSum; ans %= MOD;
            dp[beg][end] = ans;
        }
    }

    F0R(i, N) {
        F0R(j, N) {
            //if (isRange[i][j]) cout << i << " " << j << " " << dp[i][j] << endl;
        }
    }

    cout << dp[data[0]][data[M-1]] << endl;

	return 0;
}

// read the question correctly (ll vs int)
// template by bqi343


#include <bits/stdc++.h>
using namespace std;

// template {{{
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize

#define sz(x) int((x).size())
#define all(x) (x).begin(), (x).end()

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto& a : x)

#define sort_by(x, y) sort(all(x), [&](const auto& a, const auto& b) { return y; })

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;

using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;

template<typename T> void ckmin(T& a, const T& b) { a = min(a, b); }
template<typename T> void ckmax(T& a, const T& b) { a = max(a, b); }

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

namespace __input {
    template<class T1, class T2> void re(pair<T1,T2>& p);
    template<class T> void re(vector<T>& a);
    template<class T, size_t SZ> void re(array<T,SZ>& a);

    template<class T> void re(T& x) { cin >> x; }
    void re(double& x) { string t; re(t); x = stod(t); }
    template<class Arg, class... Args> void re(Arg& first, Args&... rest) {
        re(first); re(rest...);
    }

    template<class T1, class T2> void re(pair<T1,T2>& p) { re(p.f,p.s); }
    template<class T> void re(vector<T>& a) { F0R(i,sz(a)) re(a[i]); }
    template<class T, size_t SZ> void re(array<T,SZ>& a) { F0R(i,SZ) re(a[i]); }
}
using namespace __input;

namespace __output {
    template<class T1, class T2> void pr(const pair<T1,T2>& x);
    template<class T, size_t SZ> void pr(const array<T,SZ>& x);
    template<class T> void pr(const vector<T>& x);
    template<class T> void pr(const set<T>& x);
    template<class T1, class T2> void pr(const map<T1,T2>& x);

    template<class T> void pr(const T& x) { cout << x; }
    template<class Arg, class... Args> void pr(const Arg& first, const Args&... rest) {
        pr(first); pr(rest...);
    }

    template<class T1, class T2> void pr(const pair<T1,T2>& x) {
        pr("{",x.f,", ",x.s,"}");
    }
    template<class T, bool pretty = true> void prContain(const T& x) {
        if (pretty) pr("{");
        bool fst = 1; for (const auto& a: x) pr(!fst?pretty?", ":" ":"",a), fst = 0;
        if (pretty) pr("}");
    }
    template<class T> void pc(const T& x) { prContain<T, false>(x); pr("\n"); }
    template<class T, size_t SZ> void pr(const array<T,SZ>& x) { prContain(x); }
    template<class T> void pr(const vector<T>& x) { prContain(x); }
    template<class T> void pr(const set<T>& x) { prContain(x); }
    template<class T1, class T2> void pr(const map<T1,T2>& x) { prContain(x); }

    void ps() { pr("\n"); }
    template<class Arg> void ps(const Arg& first) {
        pr(first); ps();
    }
    template<class Arg, class... Args> void ps(const Arg& first, const Args&... rest) {
        pr(first," "); ps(rest...);
    }
}
using namespace __output;

#define TRACE(x) x
#define __pn(x) pr(#x, " = ")
#define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush

namespace __algorithm {
    template<typename T> void dedup(vector<T>& v) {
        sort(all(v)); v.erase(unique(all(v)), v.end());
    }
    template<typename T> typename vector<T>::iterator find(const vector<T>& v, const T& x) {
        auto it = lower_bound(all(v), x); return it != v.end() && *it == x ? it : v.end();
    }
    template<typename T> size_t index(const vector<T>& v, const T& x) {
        auto it = find(v, x); assert(it != v.end() && *it == x); return it - v.begin();
    }

    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator lower_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return lower_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator upper_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return upper_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
}
using namespace __algorithm;

struct monostate {
    friend istream& operator>>(istream& is, const __attribute__((unused))monostate& ms) { return is; }
    friend ostream& operator<<(ostream& os, const __attribute__((unused))monostate& ms) { return os; }
} ms;

template<typename W=monostate> struct wedge {
    int u, v, i; W w;
    wedge<W>(int _u=-1, int _v=-1, int _i=-1) : u(_u), v(_v), i(_i) {}
    int operator[](int loc) const { return u ^ v ^ loc; }
    friend void re(wedge& e) { re(e.u, e.v, e.w); --e.u, --e.v; }
    friend void pr(const wedge& e) { pr(e.u, "<-", e.w, "->", e.v); }
};

namespace __io {
    void setIn(string s) { freopen(s.c_str(),"r",stdin); }
    void setOut(string s) { freopen(s.c_str(),"w",stdout); }
    void setIO(string s = "") {
        ios_base::sync_with_stdio(0); cin.tie(0);
        if (sz(s)) { setIn(s+".in"), setOut(s+".out"); }
    }
}
using namespace __io;
// }}}

// modnum {{{
template<int MOD> struct modnum {
    int v;
    modnum() : v(0) {}
    modnum(ll _v) : v(_v % MOD) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    friend istream& operator >> (istream& i, modnum& n) { ll w; i >> w; n = modnum(w); return i; }
    friend ostream& operator << (ostream& o, const modnum& n) { return o << n.v; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

    modnum& operator += (const modnum& o) { v += o.v; if (v >= MOD) v -= MOD; return *this; }
    modnum& operator -= (const modnum& o) { v -= o.v; if (v < 0) v += MOD; return *this; }
    modnum& operator *= (const modnum& o) { v = int(ll(v) * ll(o.v) % MOD); return *this; }
    modnum operator - () { modnum res; if (v) res.v = MOD - v; return res; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }

    modnum pow(ll e) const {
        if (e < 0) return 1 / this->pow(-e);
        if (e == 0) return 1;
        if (e & 1) return *this * this->pow(e-1);
        return (*this * *this).pow(e/2);
    }

    modnum inv() const {
        int g = MOD, x = 0, y = 1;
        for (int r = v; r != 0; ) {
            int q = g / r;
            g %= r; swap(g, r);
            x -= q * y; swap(x, y);
        }

        assert(g == 1);
        assert(y == MOD || y == -MOD);
        return x < 0 ? x + MOD : x;
    }
    modnum& operator /= (const modnum& o) { return (*this) *= o.inv(); }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= modnum(b); }

    static int totient() {
        int tot = MOD, tmp = MOD;
        for (int p = 2; p * p <= tmp; p++) if (tmp % p == 0) {
            tot = tot / p * (p - 1);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot = tot / tmp * (tmp - 1);
        return tot;
    }

    static int primitive_root() {
        if (MOD == 1) return 0;
        if (MOD == 2) return 1;

        int tot = totient(), tmp = tot;
        vi tot_pr;
        for (int p = 2; p * p <= tmp; p++) if (tot % p == 0) {
            tot_pr.push_back(p);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot_pr.push_back(tmp);

        for (int r = 2; r < MOD; r++) if (__gcd(r, MOD) == 1) {
            bool root = true;
            for (int p : tot_pr) root &= modnum(r).pow(tot / p) != 1;
            if (root) return r;
        }
        assert(false);
    }

    static modnum generator() { static modnum g = primitive_root(); return g; }
    static int discrete_log(modnum v) {
        static const int M = ceil(sqrt(MOD));
        static unordered_map<int, int> table;
        if (table.empty()) {
            modnum e = 1;
            for (int i = 0; i < M; i++) { table[e.v] = i; e *= generator(); }
        }
        static modnum f = generator().pow(totient() - M);

        for (int i = 0; i < M; i++) {
            if (table.count(v.v)) return table[v.v] + i * M;
            v *= f;
        }
        assert(false);
    }

    static modnum unity_root(int deg) {
        assert(totient() % deg == 0);
        return generator().pow(totient() / deg);
    }

    static modnum fact(int n) {
        static vector<modnum> fact = { 1 };
        for (assert(n >= 0); fact.size() <= n; )
            fact.push_back(fact.back() * fact.size());
        return fact[n];
    }

    static modnum finv(int n) {
        static vector<modnum> finv = { 1 };
        for (assert(n >= 0); finv.size() <= n; )
            finv.push_back(finv.back() / finv.size());
        return finv[n];
    }

    static modnum ncr(int n, int r) {
        assert(n >= 0);
        if (r < 0 || n < r) return 0;
        return fact(n) * finv(r) * finv(n - r);
    }
};
// }}}
using mn = modnum<int(998244353)>;
using vmn = vector<mn>;
using vvmn = vector<vmn>;

const int MAXV = 505;

bool did[MAXV][MAXV];
mn cache[MAXV][MAXV];

vi first, last;
vpii contained;

struct range { int f, l, i; };
vector<range> ranges;

mn solve(int i, int j) {
    mn& ans = cache[i][j];
    if (did[i][j]) return ans;
    if (j-i <= 1) return ans = 1;

    vi elts;

    range low = ranges[i];
    FOR (k, i, j) {
        if (ranges[k].i < low.i)
            low = ranges[k];
        elts.pb(ranges[k].i + 1);
    }

    vpii before, between, after;
    int cbe = INT_MIN;
    auto insert = [&](int a, int b, int st, int en) {
        assert(a <= b);
        if (a == b) return;
        if (en <= low.f) before.eb(a, b);
        else if (en <= low.l) {
            if (cbe == st - 1)
                between.back().s = b;
            else
                between.eb(a, b);
            cbe = en;
        } else after.eb(a, b);
    };

    int fr = -1, hi = INT_MAX;
    FOR (k, i, j) {
        auto& r = ranges[k];
        if (hi < ranges[k].f) {
            insert(fr, k, ranges[fr].f, hi);
            fr = -1;
            hi = INT_MAX;
        }
        if (r.i == low.i) continue;

        if (fr == -1) {
            fr = k;
            hi = ranges[k].l;
        } else {
            ckmax(hi, ranges[k].l);
        }
    }
    if (fr != -1) insert(fr, j, ranges[fr].f, hi);

    mn ways = 1;
    trav (e, between) {
        ways *= solve(e.f, e.s);
    }

    mn wbef = 1;
    if (!before.empty()) {
        wbef = solve(before.front().f, before.back().s);
        F0R (sp, sz(before)) {
            wbef += solve(i, before[sp].s) * solve(before[sp].s, before.back().s);
        }
    }

    mn waft = 1;
    if (!after.empty()) {
        waft = solve(after.front().f, after.back().s);
        F0R (sp, sz(after)) {
            waft += solve(after.front().f, after[sp].s) * solve(after[sp].s, after.back().s);
        }
    }

    did[i][j] = true;
    return ans = wbef * waft * ways;
}

int main() {
    setIO();

    int N, M; re(N, M); vi strip(M); re(strip);
    trav (e, strip) --e;

    vvi locs(N);
    first.resz(N, INT_MAX), last.resz(N, -1);

    F0R (i, M) {
        locs[strip[i]].pb(i);
        ckmin(first[strip[i]], i);
        ckmax(last[strip[i]], i);
    }

    // first check if it's impossible
    set<int> alive;
    F0R (i, N) {
        auto it = alive.lower_bound(first[i]);
        if (it != alive.end() && *it < last[i]) {
            ps(0);
            return 0;
        }
        trav (e, locs[i]) alive.insert(e);
    }

    F0R (i, N) {
        ranges.pb({ first[i], last[i], i });
    }
    sort_by(ranges, a.f < b.f);

    ps(solve(0, N));

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

// template {{{
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize

#define sz(x) int((x).size())
#define all(x) (x).begin(), (x).end()

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto& a : x)

#define sort_by(x, y) sort(all(x), [&](const auto& a, const auto& b) { return y; })

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;

using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;

template<typename T> void ckmin(T& a, const T& b) { a = min(a, b); }
template<typename T> void ckmax(T& a, const T& b) { a = max(a, b); }

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

namespace __input {
    template<class T1, class T2> void re(pair<T1,T2>& p);
    template<class T> void re(vector<T>& a);
    template<class T, size_t SZ> void re(array<T,SZ>& a);

    template<class T> void re(T& x) { cin >> x; }
    void re(double& x) { string t; re(t); x = stod(t); }
    template<class Arg, class... Args> void re(Arg& first, Args&... rest) {
        re(first); re(rest...);
    }

    template<class T1, class T2> void re(pair<T1,T2>& p) { re(p.f,p.s); }
    template<class T> void re(vector<T>& a) { F0R(i,sz(a)) re(a[i]); }
    template<class T, size_t SZ> void re(array<T,SZ>& a) { F0R(i,SZ) re(a[i]); }
}
using namespace __input;

namespace __output {
    template<class T1, class T2> void pr(const pair<T1,T2>& x);
    template<class T, size_t SZ> void pr(const array<T,SZ>& x);
    template<class T> void pr(const vector<T>& x);
    template<class T> void pr(const set<T>& x);
    template<class T1, class T2> void pr(const map<T1,T2>& x);

    template<class T> void pr(const T& x) { cout << x; }
    template<class Arg, class... Args> void pr(const Arg& first, const Args&... rest) {
        pr(first); pr(rest...);
    }

    template<class T1, class T2> void pr(const pair<T1,T2>& x) {
        pr("{",x.f,", ",x.s,"}");
    }
    template<class T, bool pretty = true> void prContain(const T& x) {
        if (pretty) pr("{");
        bool fst = 1; for (const auto& a: x) pr(!fst?pretty?", ":" ":"",a), fst = 0;
        if (pretty) pr("}");
    }
    template<class T> void pc(const T& x) { prContain<T, false>(x); pr("\n"); }
    template<class T, size_t SZ> void pr(const array<T,SZ>& x) { prContain(x); }
    template<class T> void pr(const vector<T>& x) { prContain(x); }
    template<class T> void pr(const set<T>& x) { prContain(x); }
    template<class T1, class T2> void pr(const map<T1,T2>& x) { prContain(x); }

    void ps() { pr("\n"); }
    template<class Arg> void ps(const Arg& first) {
        pr(first); ps();
    }
    template<class Arg, class... Args> void ps(const Arg& first, const Args&... rest) {
        pr(first," "); ps(rest...);
    }
}
using namespace __output;

#define TRACE(x) x
#define __pn(x) pr(#x, " = ")
#define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush

namespace __algorithm {
    template<typename T> void dedup(vector<T>& v) {
        sort(all(v)); v.erase(unique(all(v)), v.end());
    }
    template<typename T> typename vector<T>::iterator find(const vector<T>& v, const T& x) {
        auto it = lower_bound(all(v), x); return it != v.end() && *it == x ? it : v.end();
    }
    template<typename T> size_t index(const vector<T>& v, const T& x) {
        auto it = find(v, x); assert(it != v.end() && *it == x); return it - v.begin();
    }

    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator lower_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return lower_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator upper_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return upper_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
}
using namespace __algorithm;

struct monostate {
    friend istream& operator>>(istream& is, const __attribute__((unused))monostate& ms) { return is; }
    friend ostream& operator<<(ostream& os, const __attribute__((unused))monostate& ms) { return os; }
} ms;

template<typename W=monostate> struct wedge {
    int u, v, i; W w;
    wedge<W>(int _u=-1, int _v=-1, int _i=-1) : u(_u), v(_v), i(_i) {}
    int operator[](int loc) const { return u ^ v ^ loc; }
    friend void re(wedge& e) { re(e.u, e.v, e.w); --e.u, --e.v; }
    friend void pr(const wedge& e) { pr(e.u, "<-", e.w, "->", e.v); }
};

namespace __io {
    void setIn(string s) { freopen(s.c_str(),"r",stdin); }
    void setOut(string s) { freopen(s.c_str(),"w",stdout); }
    void setIO(string s = "") {
        ios_base::sync_with_stdio(0); cin.tie(0);
        if (sz(s)) { setIn(s+".in"), setOut(s+".out"); }
    }
}
using namespace __io;
// }}}

// modnum {{{
template<int MOD> struct modnum {
    int v;
    modnum() : v(0) {}
    modnum(ll _v) : v(_v % MOD) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    friend istream& operator >> (istream& i, modnum& n) { ll w; i >> w; n = modnum(w); return i; }
    friend ostream& operator << (ostream& o, const modnum& n) { return o << n.v; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

    modnum& operator += (const modnum& o) { v += o.v; if (v >= MOD) v -= MOD; return *this; }
    modnum& operator -= (const modnum& o) { v -= o.v; if (v < 0) v += MOD; return *this; }
    modnum& operator *= (const modnum& o) { v = int(ll(v) * ll(o.v) % MOD); return *this; }
    modnum operator - () { modnum res; if (v) res.v = MOD - v; return res; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }

    modnum pow(ll e) const {
        if (e < 0) return 1 / this->pow(-e);
        if (e == 0) return 1;
        if (e & 1) return *this * this->pow(e-1);
        return (*this * *this).pow(e/2);
    }

    modnum inv() const {
        int g = MOD, x = 0, y = 1;
        for (int r = v; r != 0; ) {
            int q = g / r;
            g %= r; swap(g, r);
            x -= q * y; swap(x, y);
        }

        assert(g == 1);
        assert(y == MOD || y == -MOD);
        return x < 0 ? x + MOD : x;
    }
    modnum& operator /= (const modnum& o) { return (*this) *= o.inv(); }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= modnum(b); }

    static int totient() {
        int tot = MOD, tmp = MOD;
        for (int p = 2; p * p <= tmp; p++) if (tmp % p == 0) {
            tot = tot / p * (p - 1);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot = tot / tmp * (tmp - 1);
        return tot;
    }

    static int primitive_root() {
        if (MOD == 1) return 0;
        if (MOD == 2) return 1;

        int tot = totient(), tmp = tot;
        vi tot_pr;
        for (int p = 2; p * p <= tmp; p++) if (tot % p == 0) {
            tot_pr.push_back(p);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot_pr.push_back(tmp);

        for (int r = 2; r < MOD; r++) if (__gcd(r, MOD) == 1) {
            bool root = true;
            for (int p : tot_pr) root &= modnum(r).pow(tot / p) != 1;
            if (root) return r;
        }
        assert(false);
    }

    static modnum generator() { static modnum g = primitive_root(); return g; }
    static int discrete_log(modnum v) {
        static const int M = ceil(sqrt(MOD));
        static unordered_map<int, int> table;
        if (table.empty()) {
            modnum e = 1;
            for (int i = 0; i < M; i++) { table[e.v] = i; e *= generator(); }
        }
        static modnum f = generator().pow(totient() - M);

        for (int i = 0; i < M; i++) {
            if (table.count(v.v)) return table[v.v] + i * M;
            v *= f;
        }
        assert(false);
    }

    static modnum unity_root(int deg) {
        assert(totient() % deg == 0);
        return generator().pow(totient() / deg);
    }

    static modnum fact(int n) {
        static vector<modnum> fact = { 1 };
        for (assert(n >= 0); fact.size() <= n; )
            fact.push_back(fact.back() * fact.size());
        return fact[n];
    }

    static modnum finv(int n) {
        static vector<modnum> finv = { 1 };
        for (assert(n >= 0); finv.size() <= n; )
            finv.push_back(finv.back() / finv.size());
        return finv[n];
    }

    static modnum ncr(int n, int r) {
        assert(n >= 0);
        if (r < 0 || n < r) return 0;
        return fact(n) * finv(r) * finv(n - r);
    }
};
// }}}
using mn = modnum<int(998244353)>;
using vmn = vector<mn>;
using vvmn = vector<vmn>;

const int MAXV = 505;

bool did[MAXV][MAXV];
mn cache[MAXV][MAXV];

vi vals;
vi first, last;

mn solve(int i, int j) {
    if (i >= j) return 1;
    mn& ans = cache[i][j];
    if (did[i][j]) return ans;

    int k = min_element(vals.begin() + i, vals.begin() + j) - vals.begin();
    int left = first[vals[k]], right = last[vals[k]];

    mn lways = solve(i, left);
    FOR (sp, i, left) lways += solve(i, sp) * solve(sp, left);

    mn rways = solve(right+1, j);
    FOR (sp, right+1, j) rways += solve(right+1, sp) * solve(sp, j);

    mn ways = 1;
    int last = -1;
    FOR (m, left, right + 1) {
        if (vals[m] == vals[k]) {
            if (last != -1) ways *= solve(last + 1, m);
            last = m;
        }
    }

    did[i][j] = true;
    return ans = lways * ways * rways;
}

int main() {
    setIO();

    int N, M; re(N, M); vi strip(M); re(strip);
    trav (e, strip) --e;

    vvi locs(N);
    first.resz(N, INT_MAX), last.resz(N, -1);

    F0R (i, M) {
        locs[strip[i]].pb(i);
        ckmin(first[strip[i]], i);
        ckmax(last[strip[i]], i);
    }

    // first check if it's impossible
    set<int> alive;
    F0R (i, N) {
        auto it = alive.lower_bound(first[i]);
        if (it != alive.end() && *it < last[i]) {
            ps(0);
            return 0;
        }
        trav (e, locs[i]) alive.insert(e);
    }

    trav (e, strip) {
        if (vals.empty() || vals.back() != e)
            vals.pb(e);
    }

    fill(all(first), INT_MAX);
    fill(all(last), -1);
    F0R (i, sz(vals)) {
        ckmin(first[vals[i]], i);
        ckmax(last[vals[i]], i);
    }
    ps(solve(0, sz(vals)));

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

// template {{{
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize

#define sz(x) int((x).size())
#define all(x) (x).begin(), (x).end()

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto& a : x)

#define sort_by(x, y) sort(all(x), [&](const auto& a, const auto& b) { return y; })

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;

using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;

template<typename T> void ckmin(T& a, const T& b) { a = min(a, b); }
template<typename T> void ckmax(T& a, const T& b) { a = max(a, b); }

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

namespace __input {
    template<class T1, class T2> void re(pair<T1,T2>& p);
    template<class T> void re(vector<T>& a);
    template<class T, size_t SZ> void re(array<T,SZ>& a);

    template<class T> void re(T& x) { cin >> x; }
    void re(double& x) { string t; re(t); x = stod(t); }
    template<class Arg, class... Args> void re(Arg& first, Args&... rest) {
        re(first); re(rest...);
    }

    template<class T1, class T2> void re(pair<T1,T2>& p) { re(p.f,p.s); }
    template<class T> void re(vector<T>& a) { F0R(i,sz(a)) re(a[i]); }
    template<class T, size_t SZ> void re(array<T,SZ>& a) { F0R(i,SZ) re(a[i]); }
}
using namespace __input;

namespace __output {
    template<class T1, class T2> void pr(const pair<T1,T2>& x);
    template<class T, size_t SZ> void pr(const array<T,SZ>& x);
    template<class T> void pr(const vector<T>& x);
    template<class T> void pr(const set<T>& x);
    template<class T1, class T2> void pr(const map<T1,T2>& x);

    template<class T> void pr(const T& x) { cout << x; }
    template<class Arg, class... Args> void pr(const Arg& first, const Args&... rest) {
        pr(first); pr(rest...);
    }

    template<class T1, class T2> void pr(const pair<T1,T2>& x) {
        pr("{",x.f,", ",x.s,"}");
    }
    template<class T, bool pretty = true> void prContain(const T& x) {
        if (pretty) pr("{");
        bool fst = 1; for (const auto& a: x) pr(!fst?pretty?", ":" ":"",a), fst = 0;
        if (pretty) pr("}");
    }
    template<class T> void pc(const T& x) { prContain<T, false>(x); pr("\n"); }
    template<class T, size_t SZ> void pr(const array<T,SZ>& x) { prContain(x); }
    template<class T> void pr(const vector<T>& x) { prContain(x); }
    template<class T> void pr(const set<T>& x) { prContain(x); }
    template<class T1, class T2> void pr(const map<T1,T2>& x) { prContain(x); }

    void ps() { pr("\n"); }
    template<class Arg> void ps(const Arg& first) {
        pr(first); ps();
    }
    template<class Arg, class... Args> void ps(const Arg& first, const Args&... rest) {
        pr(first," "); ps(rest...);
    }
}
using namespace __output;

#define TRACE(x) x
#define __pn(x) pr(#x, " = ")
#define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush

namespace __algorithm {
    template<typename T> void dedup(vector<T>& v) {
        sort(all(v)); v.erase(unique(all(v)), v.end());
    }
    template<typename T> typename vector<T>::iterator find(const vector<T>& v, const T& x) {
        auto it = lower_bound(all(v), x); return it != v.end() && *it == x ? it : v.end();
    }
    template<typename T> size_t index(const vector<T>& v, const T& x) {
        auto it = find(v, x); assert(it != v.end() && *it == x); return it - v.begin();
    }

    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator lower_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return lower_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator upper_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return upper_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
}
using namespace __algorithm;

struct monostate {
    friend istream& operator>>(istream& is, const __attribute__((unused))monostate& ms) { return is; }
    friend ostream& operator<<(ostream& os, const __attribute__((unused))monostate& ms) { return os; }
} ms;

template<typename W=monostate> struct wedge {
    int u, v, i; W w;
    wedge<W>(int _u=-1, int _v=-1, int _i=-1) : u(_u), v(_v), i(_i) {}
    int operator[](int loc) const { return u ^ v ^ loc; }
    friend void re(wedge& e) { re(e.u, e.v, e.w); --e.u, --e.v; }
    friend void pr(const wedge& e) { pr(e.u, "<-", e.w, "->", e.v); }
};

namespace __io {
    void setIn(string s) { freopen(s.c_str(),"r",stdin); }
    void setOut(string s) { freopen(s.c_str(),"w",stdout); }
    void setIO(string s = "") {
        ios_base::sync_with_stdio(0); cin.tie(0);
        if (sz(s)) { setIn(s+".in"), setOut(s+".out"); }
    }
}
using namespace __io;
// }}}

// modnum {{{
template<int MOD> struct modnum {
    int v;
    modnum() : v(0) {}
    modnum(ll _v) : v(_v % MOD) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    friend istream& operator >> (istream& i, modnum& n) { ll w; i >> w; n = modnum(w); return i; }
    friend ostream& operator << (ostream& o, const modnum& n) { return o << n.v; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

    modnum& operator += (const modnum& o) { v += o.v; if (v >= MOD) v -= MOD; return *this; }
    modnum& operator -= (const modnum& o) { v -= o.v; if (v < 0) v += MOD; return *this; }
    modnum& operator *= (const modnum& o) { v = int(ll(v) * ll(o.v) % MOD); return *this; }
    modnum operator - () { modnum res; if (v) res.v = MOD - v; return res; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }

    modnum pow(ll e) const {
        if (e < 0) return 1 / this->pow(-e);
        if (e == 0) return 1;
        if (e & 1) return *this * this->pow(e-1);
        return (*this * *this).pow(e/2);
    }

    modnum inv() const {
        int g = MOD, x = 0, y = 1;
        for (int r = v; r != 0; ) {
            int q = g / r;
            g %= r; swap(g, r);
            x -= q * y; swap(x, y);
        }

        assert(g == 1);
        assert(y == MOD || y == -MOD);
        return x < 0 ? x + MOD : x;
    }
    modnum& operator /= (const modnum& o) { return (*this) *= o.inv(); }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= modnum(b); }

    static int totient() {
        int tot = MOD, tmp = MOD;
        for (int p = 2; p * p <= tmp; p++) if (tmp % p == 0) {
            tot = tot / p * (p - 1);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot = tot / tmp * (tmp - 1);
        return tot;
    }

    static int primitive_root() {
        if (MOD == 1) return 0;
        if (MOD == 2) return 1;

        int tot = totient(), tmp = tot;
        vi tot_pr;
        for (int p = 2; p * p <= tmp; p++) if (tot % p == 0) {
            tot_pr.push_back(p);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot_pr.push_back(tmp);

        for (int r = 2; r < MOD; r++) if (__gcd(r, MOD) == 1) {
            bool root = true;
            for (int p : tot_pr) root &= modnum(r).pow(tot / p) != 1;
            if (root) return r;
        }
        assert(false);
    }

    static modnum generator() { static modnum g = primitive_root(); return g; }
    static int discrete_log(modnum v) {
        static const int M = ceil(sqrt(MOD));
        static unordered_map<int, int> table;
        if (table.empty()) {
            modnum e = 1;
            for (int i = 0; i < M; i++) { table[e.v] = i; e *= generator(); }
        }
        static modnum f = generator().pow(totient() - M);

        for (int i = 0; i < M; i++) {
            if (table.count(v.v)) return table[v.v] + i * M;
            v *= f;
        }
        assert(false);
    }

    static modnum unity_root(int deg) {
        assert(totient() % deg == 0);
        return generator().pow(totient() / deg);
    }

    static modnum fact(int n) {
        static vector<modnum> fact = { 1 };
        for (assert(n >= 0); fact.size() <= n; )
            fact.push_back(fact.back() * fact.size());
        return fact[n];
    }

    static modnum finv(int n) {
        static vector<modnum> finv = { 1 };
        for (assert(n >= 0); finv.size() <= n; )
            finv.push_back(finv.back() / finv.size());
        return finv[n];
    }

    static modnum ncr(int n, int r) {
        assert(n >= 0);
        if (r < 0 || n < r) return 0;
        return fact(n) * finv(r) * finv(n - r);
    }
};
// }}}
using mn = modnum<int(998244353)>;
using vmn = vector<mn>;
using vvmn = vector<vmn>;

const int MAXV = 505;

bool did[MAXV][MAXV];
mn cache[MAXV][MAXV];

vi vals;
vi first, last;

mn solve(int i, int j) {
    if (i >= j) return 1;
    mn& ans = cache[i][j];
    if (did[i][j]) return ans;

    int k = min_element(vals.begin() + i, vals.begin() + j) - vals.begin();
    int left = first[vals[k]], right = last[vals[k]];

    mn lways = solve(i, left);
    FOR (sp, i, left) lways += solve(i, sp) * solve(sp, left);

    mn rways = solve(right+1, j);
    FOR (sp, right+1, j) rways += solve(right+1, sp) * solve(sp, j);

    mn ways = 1;
    int last = -1;
    FOR (m, left, right + 1) {
        if (vals[m] == vals[k]) {
            if (last != -1) ways *= solve(last + 1, m);
            last = m;
        }
    }

    return ans = lways * ways * rways;
}

int main() {
    setIO();

    int N, M; re(N, M); vi strip(M); re(strip);
    trav (e, strip) --e;

    vvi locs(N);
    first.resz(N, INT_MAX), last.resz(N, -1);

    F0R (i, M) {
        locs[strip[i]].pb(i);
        ckmin(first[strip[i]], i);
        ckmax(last[strip[i]], i);
    }

    // first check if it's impossible
    set<int> alive;
    F0R (i, N) {
        auto it = alive.lower_bound(first[i]);
        if (it != alive.end() && *it < last[i]) {
            ps(0);
            return 0;
        }
        trav (e, locs[i]) alive.insert(e);
    }

    trav (e, strip) {
        if (vals.empty() || vals.back() != e)
            vals.pb(e);
    }

    fill(all(first), INT_MAX);
    fill(all(last), -1);
    F0R (i, sz(vals)) {
        ckmin(first[vals[i]], i);
        ckmax(last[vals[i]], i);
    }
    ps(solve(0, sz(vals)));

    return 0;
}