Problem:
Score : 2000 points

Problem Statement

Let us consider a grid of squares with N rows and N columns.
Arbok has cut out some part of the grid so that, for each i = 1, 2, \ldots, N, the bottommost h_i squares are remaining in the i-th column from the left.
Now, he wants to place rooks into some of the remaining squares.

A rook is a chess piece that occupies one square and can move horizontally or vertically, through any number of unoccupied squares.
A rook can not move through squares that have been cut out by Arbok.

Let's say that a square is covered if it either contains a rook, or a rook can be moved to this square in one move.

Find the number of ways to place rooks into some of the remaining squares so that every remaining square is covered, modulo 998244353.

Constraints

1 \leq N \leq 400

1 \leq h_i \leq N

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
h_1 h_2 ... h_N

Output

Print the number of ways to place rooks into some of the remaining squares so that every remaining square is covered, modulo 998244353.

Sample Input 1

2
2 2

Sample Output 1

11

Any placement with at least two rooks is fine. There are 11 such placements.

Sample Input 2

3
2 1 2

Sample Output 2

17

The following 17 rook placements satisfy the conditions (R denotes a rook, * denotes an empty square):

R * * R * * R R R R R R
**R R** R*R R** *R* **R

R * R * * R * R * * R R
R*R *RR RR* R*R RRR RR*

R R R R R * * R R R
R*R *RR RRR RRR RRR

Sample Input 3

4
1 2 4 1

Sample Output 3

201

Sample Input 4

10
4 7 4 8 4 6 8 2 3 6

Sample Output 4

263244071

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
//#define cerr if (false) cerr
#define db(x) cerr << #x << "=" << x << endl
#define db2(x, y) cerr << #x << "=" << x << "," << #y << "=" << y << endl
#define db3(x, y, z) cerr << #x << "=" << x << "," << #y << "=" << y << "," << #z << "=" << z << endl
#define dbv(v) cerr << #v << "="; for (auto _x : v) cerr << _x << ", "; cerr << endl
#define dba(a, n) cerr << #a << "="; for (int _i = 0; _i < (n); ++_i) cerr << a[_i] << ", "; cerr << endl
template <typename A, typename B>
ostream& operator<<(ostream& os, const pair<A, B>& x) {
	return os << "(" << x.first << "," << x.second << ")";
}
typedef long long ll;
typedef long double ld;
const int MOD = 998244353;
struct Mint {
	int val;
	Mint() { val = 0; }
	Mint(const ll& x) {
		val = (-MOD <= x && x < MOD) ? x : x % MOD;
		if (val < 0) val += MOD;
	}
	friend bool operator==(const Mint& a, const Mint& b) { return a.val == b.val; }
	friend bool operator!=(const Mint& a, const Mint& b) { return !(a == b); }
	friend bool operator<(const Mint& a, const Mint& b) { return a.val < b.val; }
	Mint& operator+=(const Mint& m) { if ((val += m.val) >= MOD) val -= MOD; return *this; }
	Mint& operator-=(const Mint& m) { if ((val -= m.val) < 0) val += MOD; return *this; }
	Mint& operator*=(const Mint& m) { val = (ll)val * m.val % MOD; return *this; }
	friend Mint modex(Mint a, ll p) {
		assert(p >= 0);
		Mint ans = 1;
		for (; p; p >>= 1, a *= a) if (p & 1) ans *= a;
		return ans;
	}
	Mint& operator/=(const Mint& m) { return *this *= modex(m, MOD - 2); }
	Mint& operator++() { return *this += 1; }
	Mint& operator--() { return *this -= 1; }
	Mint operator++(int) { Mint result(*this); *this += 1; return result; }
	Mint operator--(int) { Mint result(*this); *this -= 1; return result; }
	Mint operator-() const { return Mint(-val); }
	friend Mint operator+(Mint a, const Mint& b) { return a += b; }
	friend Mint operator-(Mint a, const Mint& b) { return a -= b; }
	friend Mint operator*(Mint a, const Mint& b) { return a *= b; }
	friend Mint operator/(Mint a, const Mint& b) { return a /= b; }
	friend ostream& operator<<(ostream& os, const Mint& x) { return os << x.val; }
};
const int MAXS = 405 * 405;
int H[405];
int curId;
pair<int, int> R[MAXS];
Mint F[MAXS][405], G[MAXS][405];
const int MAXN = 405;
Mint fac[MAXN], invfac[MAXN], p2[MAXN];
Mint binom(ll a, ll b) {
	if (b < 0) return 0;
	if (b > a) return 0;
	return fac[a] * invfac[b] * invfac[a - b];
}
int go(int s, int e, int h) {
	vector<int> ch;
	int st = s;
	for (int i = s; i <= e; ++i) {
		assert(H[i] >= h);
		if (H[i] == h) {
			if (i - 1 >= st) ch.push_back(go(st, i - 1, h + 1));
			st = i + 1;
		}
	}
	if (e >= st) ch.push_back(go(st, e, h + 1));
	int curlen = 0;
	vector<Mint> f(1, 1), g(1, 1);
	for (int x : ch) {
		int len = R[x].second - R[x].first + 1;
		vector<Mint> nf(len + curlen + 1), ng(len + curlen + 1);
		for (int i = 0; i <= len; ++i) {
			for (int j = 0; j <= curlen; ++j) {
				nf[j + i] += f[j] * F[x][i];
				ng[j + i] += g[j] * G[x][i];
			}
		}
		swap(nf, f);
		swap(ng, g);
		curlen += len;
	}
	int x = curId;
	int totlen = e - s + 1;
	vector<Mint> ng(totlen + 1);
	for (int i = 0; i <= curlen; ++i) {
		ng[i + totlen - curlen] = g[i];
	}
	swap(g, ng);
	f.resize(totlen + 1);
	for (int i = 0; i <= totlen; ++i) {
		F[x][i] += g[i];
		G[x][i] += g[i] * p2[totlen - i];
		F[x][i] += f[i] * (p2[totlen - i] - 1);
		for (int j = 1; j <= i; ++j) {
			G[x][i - j] += p2[totlen - i] * binom(i, j) * g[i];
			F[x][i - j] += p2[totlen - i] * binom(i, j) * f[i];
		}
	}
	R[x] = {s, e};
	return curId++;
}
int main() {
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; ++i) scanf("%d", &H[i]);
	p2[0] = 1;
	for (int i = 1; i < MAXN; ++i) p2[i] = p2[i - 1] * 2;
	fac[0] = 1;
	for (int i = 1; i < MAXN; ++i)
		fac[i] = fac[i - 1] * i;
	invfac[MAXN - 1] = 1 / fac[MAXN - 1];
	for (int i = MAXN - 2; i >= 0; --i)
		invfac[i] = invfac[i + 1] * (i + 1);
	int x = go(0, n - 1, 1);
	printf("%d\n", F[x][0].val);
}