#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using ll = long long;
using namespace std;
using namespace __gnu_pbds;
template<class  T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template<class  T>
using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
struct SegTree {
    vector<ll> t, add, a;
    ll sz;
    SegTree(vector<ll> v) {
        sz = v.size();
        a = v;
        t.resize(4*sz);
        add.resize(4*sz);
        build(1, 0, sz);
    }
    void build(ll v, ll tl, ll tr) {
        if (tl+1==tr) {
            t[v]=a[tl];
        }
        else {
            ll tm = (tl+tr)/2;
            build(2*v, tl, tm);
            build(2*v+1, tm, tr);
            t[v]=t[2*v]+t[2*v+1];
        }
    }
    void push(ll v, ll tl, ll tr) {
        t[v]+=add[v]*(tr-tl);
        if (tl+1!=tr) {
            add[2*v]+=add[v];
            add[2*v+1]+=add[v];
        }
        add[v]=0;
    }
    ll get(ll l, ll r) {
        return _get(1, 0, sz, l, r);
    }
    ll _get(ll v, ll tl, ll tr, ll l, ll r) {
        push(v, tl, tr);
        if (tl==l&&tr==r)return t[v];
        ll tm = (tr+tl)/2;
        if (r<=tm)return _get(2*v, tl, tm, l, r);
        if (l>=tm)return _get(2*v+1, tm, tr, l, r);
        return _get(2*v, tl, tm, l, tm)+_get(2*v+1, tm, tr, tm, r);
    }
    void update(ll l, ll r, ll val) {
        _update(1, 0, sz, l, r, val);
    }
    void _update(ll v, ll tl, ll tr, ll l, ll r, ll val) {
        push(v, tl, tr);
        if (l<=tl&&tr<=r) {
            add[v]+=val;
            push(v, tl, tr);
            return;
        }
        if (l>=tr||tl>=r)return;
        ll tm = (tl+tr)/2;
        _update(2*v, tl, tm, l, r, val);
        _update(2*v+1, tm, tr, l, r, val);
        t[v]=t[2*v]+t[2*v+1];
    }
};
template<typename T, typename U>
istream &operator>>(istream &in, pair<T, U> &p) {
    in>>p.first>>p.second;
    return in;
}
template<typename T, typename U>
ostream &operator<<(ostream &out, const pair<T, U> p) {
    out<<p.first<<" "<<p.second<<"\n";
    return out;
}
template<typename T>
istream &operator>>(istream &in, vector<T> &v) {
    for (int i = 0; i<v.size(); i++)in>>v[i];
    return in;
}

template<typename T>
ostream &operator<<(ostream &out, const vector<T> v) {
    for (auto &x: v)out<<x<<" ";
    return out;
}
vector<ll> prefix_func(string s) {
    ll n = s.size();
    vector<ll> prefix(n);
    prefix[0]=0;
    for (int i = 1; i<n; i++) {
        ll j = prefix[i-1];
        while (j>0&&s[i]!=s[j]) {
            j = prefix[j-1];
        }
        if (s[i]==s[j])j++;
        prefix[i]=j;
    }
    return prefix;
}
vector<ll> z_func(string s) {
    ll n = s.size();
    vector<ll> z(n, 0);
    ll l = 0, r = -1;
    for (int i = 1; i<n; i++) {
        z[i]=max(r-i+1, z[i-l]);
        while (i+z[i]<n&&s[i+z[i]]==s[z[i]])z[i]++;
        if (i+z[i]-1>r) {
            l = i;
            r = i+z[i]-1;
        }
    }
    z[0]=n;
    return z;
}
ll mod = 998244353;
ll pw(ll a, ll b) {
    if (b==0)return 1;
    ll x = pw(a, b/2);
    x = x*x%mod;
    if (b%2)x = x*a%mod;
    return x;
}
vector<ll> calcans(vector<ll> &v) {
    ll n = v.size();
    vector<vector<ll>> vx(n);
    for (int i = n-1; i>-1; i--) {
        vx[v[i]].push_back(i);
    }
    set<ll> id;
    for (int i = 0; i<n; i++) {
        if (vx[i].size())id.insert(vx[i].back());
    }
    vector<ll> ans;
    ll cur = -1;
    for (int i = 0; i<n; i++) {
        ll ind1 = *id.begin();
        if (v[ind1]==cur&&id.size()>1) {
            ind1 = *(++id.begin());
        }
        cur = v[ind1];
        ans.push_back(ind1);
        id.erase(ind1);
        vx[v[ind1]].pop_back();
        if (vx[v[ind1]].size())id.insert(vx[v[ind1]].back());
    }
    vector<ll> pos(n);
    for (int i = 0; i<n; i++) {
        pos[ans[i]]=i+1;
    }
    return ans;
}
vector<vector<ll>> g;
vector<ll> is;
vector<ll> sz;
vector<vector<ll>> dp;
ll n;
vector<ll> fact, fact1;
ll C(ll n, ll k) {
    if (k<0||k>n)return 0;
    return fact[n]*fact1[k]%mod*fact1[n-k]%mod;
}
void dfs(ll v) {
    sz[v]=1;
    for (auto to: g[v]){dfs(to); sz[v]+=sz[to];}
    vector<ll> dp2(n+2);
    dp2[0]=1;
    for (auto to: g[v]) {
        for (int i = n; i>=0; i--) {
            dp2[i]*=dp[to][0];
            dp2[i]%=mod;
            for (int j = 1; j<=i; j++) {
                dp2[i]+=dp2[i-j]*dp[to][j]%mod;
                dp2[i]%=mod;
            }
        }
    }
    if (!is[v]) {
        for (int j = 0; j<=n; j++) {
            dp[v][j]=dp2[j];
        }
    }
    else {
        for (int j = 0; j<=n; j++) {
            for (int i = 1; i+j-1<=n; i++) {
                dp[v][j]+=dp2[i+j-1]*C(i+j-1, i-1)%mod+dp2[i+j-1]*C(i+j-1, j-1)%mod;
                dp[v][j]%=mod;
                for (auto to: g[v]) {
                    if (i+j-1<=n)dp[v][j]-=dp[to][i+j-1]*C(i+j-1, j-1);
                    dp[v][j]+=mod;
                    dp[v][j]%=mod;
                }
            }

        }
    }
}
void solve() {
    ll k;
    cin>>n>>k;
    g.resize(n);
    is.resize(n);
    sz.resize(n);
    dp = vector<vector<ll>> (n, vector<ll> (n+1, 0));
    vector<ll> v(k);
    cin>>v;
    for (int i = 0; i<n-1; i++) {
        ll p;
        cin>>p;
        g[p-1].push_back(i+1);
    }
    sort(v.begin(), v.end());
    for (int i = 0; i<k; i++) {
        is[v[i]-1]=1;
    }
    dfs(0);
    ll sum = 0;
    for (int i = 0; i<=n; i++) {
        sum+=dp[0][i];
        sum%=mod;
    }
    cout<<dp<<"\n";
    cout<<sum<<"\n";
}
signed main() {
#ifdef home
    freopen(".in", "r", stdin);
    freopen(".out", "w", stdout);
#else
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    ll t=1;
    //cin>>t;
    fact.push_back(1);
    fact1.push_back(1);
    fact.resize(10000);
    fact1.resize(10000);
    for (int i = 1; i<10000; i++) {
        fact[i]=fact[i-1]*i%mod;
        fact1[i]=pw(fact[i], mod-2);
    }
    while (t--)solve();
}