#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> ii;
const int INF = 1e9;
const ll LINF = 1e18;
const int MOD = 998244353;
void add(int& a, int b) {
a += b;
if (a >= MOD) a -= MOD;
if (a < 0) a += MOD;
}
// Hai đồ thị khác nhau khi tập cạnh của chúng khác nhau (G1 != G2 <=> E1 != E2)
// Tập cạnh của cây dfs cũng chính là tập cạnh của đồ thị ban đầu
// Nên đối với bài này để cho đơn giản thì với mỗi tập cạnh, ta sẽ xét nó dưới dạng một cây dfs
// Cây dfs cho đồ thị vô hướng thì có đúng 2 loại cạnh:
// + Cạnh của cây dfs (tree edge) (cạnh nét liền)
// + Cạnh ngược (back edge) (cạnh nét đứt)
// Độ sâu (depth) của một đỉnh trên cây chính bằng số cạnh đi từ đỉnh đó lên đến gốc của cây
// Ở bài này để cho thuận tiện thì ta định nghĩa độ sâu là số đỉnh thay vì số cạnh
// Khi biết độ sâu của một đỉnh thì ta cũng biết được số tổ tiên của nó
int n;
int a[20];
int pow2[20]; // pow2[i] = 2^i
int dp[20][20]; // dp[i][depth] = Số cây dfs thoả mãn khi xét đến đỉnh thứ i
// và đỉnh thứ i có độ sâu là depth trong cây dfs
void precompute() {
pow2[0] = 1;
for (int i = 1; i <= n; i++) {
pow2[i] = pow2[i - 1] * 2;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
precompute();
// Khi thêm đỉnh a(i) vào thì để thoả mãn,
// a(i) phải là con của a(i - 1) hoặc là con của một đỉnh tổ tiên của a(i - 1)
dp[1][1] = 1;
for (int i = 1; i < n; i++) {
for (int depth = 1; depth <= i; depth++) {
for (int next_depth = 2; next_depth <= depth + 1; next_depth++) {
add(dp[i + 1][next_depth], dp[i][depth]); // không thêm cạnh ngược
add(dp[i + 1][next_depth], 1ll * dp[i][depth] * (pow2[next_depth - 2] - 1) % MOD); // thêm cạnh ngược
}
}
}
int ans = 0;
for (int depth = 1; depth <= n; depth++) {
add(ans, dp[n][depth]);
}
cout << ans << '\n';
}