Problem:
H: Infinite Problems
問題
問題 $1, \ldots, N$ からなるコンテストがあり、問題 $i$ の配点は $a_i$ 点です。ただし、最初に回答権のある問題は問題 $1$ のみであり、問題 $i$ の回答権を得るためには問題 $p_i$ に正解している必要があります。この条件を満たした上で、解いた問題の点数の合計が $K$ 点となる組み合わせは何通りありますか？
答えを $998244353$ で割った余りを出力してください。
入力形式
$N$ $K$
$a_{1}$ $\ldots$ $a_{N}$
$p_{2}$ $\ldots$ $p_{N}$
制約
$1 \leq N \leq 2{,}000$
$1 \leq K \leq 2{,}000$
$1 \leq a_i \leq 2{,}000\ (1\leq i \leq N)$
$1 \leq p_i \lt i\ (2\leq i \leq N)$
入力は全て整数で与えられる。
出力形式
答えを一行に出力し、最後に改行を入れてください。
入力例 1
4 6
1 2 3 10
1 2 1
出力例 1
1
問題 $1,2,3$ を解くと合計 $6$ 点になります。
このとき問題 $4$ に解答権がありますが、解かなくてもよいです。
入力例 2
2 5
1 1
1
出力例 2
0
合計が $5$ 点となる解き方は存在しません。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;
using mint = modint998244353;
using ll   = long long;
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define reps(i, a, b) for (ll i = (a); i < (b); i++)
bool chmin(auto &a, auto b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto &a, auto b) { return a < b ? a = b, 1 : 0; }
vector<ll> sin45 = {0, 1, 1, 1, 0, -1, -1, -1}, cos45 = {1, 1, 0, -1, -1, -1, 0, 1};
vector<ll> dx = {0, 1, 0, -1};
vector<ll> dy = {1, 0, -1, 0};
#define ft first
#define sd second
#define all(x) std::begin(x), std::end(x)
#define mp(a, b) make_pair(a, b)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb(x) push_back(x)
#define so(z) sort(z.begin(), z.end())
#define sor(z) sort(z.rbegin(), z.rend())
#define vec vector<ll>
#define vecc vector<vector<ll>>

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    ll n, k;
    cin >> n >> k;

    vector<ll> a(n);
    vector<ll> p(n);
    vector<vector<ll>> g(n);

    rep(i, n) { cin >> a[i]; }
    rep(i, n - 1) {
        cin >> p[i + 1];
        p[i + 1]--;
        g[p[i + 1]].push_back(i + 1);
    }

    auto dfs = [&](auto dfs, ll x) -> vector<mint> {
        vector<mint> sum(k + 1, mint(0));
        if (a[x] <= k) sum[a[x]]++;
        
        for (ll to : g[x]) {
            // cerr << to << "\n";
            vector<mint> v = dfs(dfs, to);
            sum            = atcoder::convolution<mint>(sum, v);
            sum.resize(k + 1);
        }
        sum[0] = 1;

        // cout << "x = " << x << endl;
        // for (auto kk : sum) { cout << kk.val() << " "; }
        // cout << endl;
        return sum;
    };

    vector<mint> sum = dfs(dfs, 0);

    cout << sum[k].val() << endl;
}
accuracy: 1
time_ms: 170
memory_kb: 3968
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;
using mint = modint998244353;
using ll   = long long;
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define reps(i, a, b) for (ll i = (a); i < (b); i++)
bool chmin(auto &a, auto b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto &a, auto b) { return a < b ? a = b, 1 : 0; }
vector<ll> sin45 = {0, 1, 1, 1, 0, -1, -1, -1}, cos45 = {1, 1, 0, -1, -1, -1, 0, 1};
vector<ll> dx = {0, 1, 0, -1};
vector<ll> dy = {1, 0, -1, 0};
#define ft first
#define sd second
#define all(x) std::begin(x), std::end(x)
#define mp(a, b) make_pair(a, b)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb(x) push_back(x)
#define so(z) sort(z.begin(), z.end())
#define sor(z) sort(z.rbegin(), z.rend())
#define vec vector<ll>
#define vecc vector<vector<ll>>

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    ll n, k;
    cin >> n >> k;

    vector<ll> a(n);
    vector<ll> p(n);
    vector<vector<ll>> g(n);

    rep(i, n) { cin >> a[i]; }
    rep(i, n - 1) {
        cin >> p[i + 1];
        p[i + 1]--;
        g[p[i + 1]].push_back(i + 1);
    }

    auto dfs = [&](auto dfs, ll x) -> vector<mint> {
        vector<mint> sum(k + 1, mint(0));
        sum[0] = 1;
        if (a[x] <= k) sum[a[x]]++;

        for (ll to : g[x]) {
            // cerr << to << "\n";
            vector<mint> v = dfs(dfs, to);
            sum            = atcoder::convolution<mint>(sum, v);
            sum.resize(k + 1);
        }

        // sum[0] = 0;

        // cout << "x = " << x << endl;
        // for (auto kk : sum) { cout << kk.val() << " "; }
        // cout << endl;
        return sum;
    };

    vector<mint> sum = dfs(dfs, 0);

    cout << sum[k].val() << endl;
}
accuracy: 0.038461538461538464
time_ms: 100
memory_kb: 3840
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> bool chmin(T& a, T b) { return a > b ? a = b, true : false; }
template<class T> bool chmax(T& a, T b) { return a < b ? a = b, true : false; }
template<typename T>
concept Iterable = requires(T t) { std::begin(t); std::end(t); };
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
ostream& operator<<(ostream& os, const T& container) { for (auto& element : container) os << element << ' '; return os; }
template<typename R>
	requires ranges::range<R> && (!is_same_v<decay_t<R>, string>) && (!is_same_v<decay_t<R>, const char*>)
ostream& operator<<(ostream& os, R&& range) { for (auto& element : range)os << element << ' '; return os; }
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
istream& operator>>(std::istream& is, T& container) { for (auto& e : container)is >> e; return is; }
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
template<class T = ll> struct Edge {
	int to;
	T weight;
	bool operator==(Edge e) { return this->to == e.to and this->weight == e.weight; }
	bool operator<(Edge e) { return this->to == e.to ? this->weight < e.weight : this->to < e.to; }
};
#ifdef _DEBUG
#define SHOW(n) {const auto& _ret = n; cerr << #n << ": " << _ret << endl;}
#define MSG(x) cerr << x << endl;
#else
#define SHOW(n)
#define MSG(x)
#endif

////AtCoder Library
//#include <atcoder/all>
//using namespace atcoder;
////using mint = modint998244353;
////using mint = modint1000000007;
////using mint1 = dynamic_modint<0>;
//using mint = modint;
////mint::set_mod();
//istream& operator>>(istream& is, mint& x) { ll r; is >> r; x = r; return is; }
//ostream& operator<<(ostream& os, mint& x) { os << x.val(); return os; }

//boost
//#include <boost/multiprecision/cpp_int.hpp>
//using namespace boost::multiprecision;
//using l3 = int128_t;



#define REP(i, n) for(int i = 0; i < n; i++)
#define P pair<ll, ll>
ll powmod(ll a, ll b, ll mod = 998244353) {
	ll res = 1;
	a %= mod;
	while (b > 0) {
		if (b % 2 == 1) res = res * a % mod;
		a = a * a % mod;
		b /= 2;
	}
	return res;
}
vector<ll> f(210000);
ll ncr(ll n, ll r, ll mod = 998244353) {
	return f[n] * powmod(f[r], mod - 2) % mod * powmod(f[n - r], mod - 2) % mod;
}
ll mod = 998244353;
vector<ll> g[3100], v(3100), p(3100);

vector<P> dfs(int a) {
	vector<P> now;
	now.push_back(P(v[a], 1));
	for (auto& i : g[a])
	{
		vector<P> res = dfs(i);
		res.push_back(P(0, 1));
		vector<ll> t(2010);
		for (auto& p1 : now)
		{
			for (auto& p2 : res) {
				if (p1.first + p2.first > 2000)continue;
				t[p1.first + p2.first] += p1.second * p2.second % mod;
				t[p1.first + p2.first] %= mod;
			}
		}
		vector<P> ne;
		REP(i, 2010) {
			if (t[i] > 0)ne.push_back(P(i, t[i]));
		}
		now = ne;
		//cout << a << " " << now.size() << endl;
	}
	return now;
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	ll n, k;
	cin >> n >> k;
	REP(i, n)cin >> v[i];
	REP(i, n - 1) {
		cin >> p[i + 1];
		p[i + 1]--;
		g[p[i + 1]].push_back(i + 1);
	}
	vector<P> ans = dfs(0);
	REP(i, ans.size()) {
		//cout << i << " " << ans[i].first << " " << ans[i].second << endl;
		if (ans[i].first == k) {
			cout << ans[i].second << endl;
			return 0;
		}
	}
	cout << 0 << endl;
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 5504
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> bool chmin(T& a, T b) { return a > b ? a = b, true : false; }
template<class T> bool chmax(T& a, T b) { return a < b ? a = b, true : false; }
template<typename T>
concept Iterable = requires(T t) { std::begin(t); std::end(t); };
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
ostream& operator<<(ostream& os, const T& container) { for (auto& element : container) os << element << ' '; return os; }
template<typename R>
	requires ranges::range<R> && (!is_same_v<decay_t<R>, string>) && (!is_same_v<decay_t<R>, const char*>)
ostream& operator<<(ostream& os, R&& range) { for (auto& element : range)os << element << ' '; return os; }
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
istream& operator>>(std::istream& is, T& container) { for (auto& e : container)is >> e; return is; }
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
template<class T = ll> struct Edge {
	int to;
	T weight;
	bool operator==(Edge e) { return this->to == e.to and this->weight == e.weight; }
	bool operator<(Edge e) { return this->to == e.to ? this->weight < e.weight : this->to < e.to; }
};
#ifdef _DEBUG
#define SHOW(n) {const auto& _ret = n; cerr << #n << ": " << _ret << endl;}
#define MSG(x) cerr << x << endl;
#else
#define SHOW(n)
#define MSG(x)
#endif

////AtCoder Library
//#include <atcoder/all>
//using namespace atcoder;
////using mint = modint998244353;
////using mint = modint1000000007;
////using mint1 = dynamic_modint<0>;
//using mint = modint;
////mint::set_mod();
//istream& operator>>(istream& is, mint& x) { ll r; is >> r; x = r; return is; }
//ostream& operator<<(ostream& os, mint& x) { os << x.val(); return os; }

//boost
//#include <boost/multiprecision/cpp_int.hpp>
//using namespace boost::multiprecision;
//using l3 = int128_t;



#define REP(i, n) for(int i = 0; i < n; i++)
#define P pair<ll, ll>
ll powmod(ll a, ll b, ll mod = 998244353) {
	ll res = 1;
	a %= mod;
	while (b > 0) {
		if (b % 2 == 1) res = res * a % mod;
		a = a * a % mod;
		b /= 2;
	}
	return res;
}
vector<ll> f(210000);
ll ncr(ll n, ll r, ll mod = 998244353) {
	return f[n] * powmod(f[r], mod - 2) % mod * powmod(f[n - r], mod - 2) % mod;
}
ll mod = 998244353;
vector<ll> g[3100], v(3100), p(3100);

vector<P> dfs(int a) {
	vector<P> now;
	now.push_back(P(v[a], 1));
	now.push_back(P(0, 1));
	for (auto& i : g[a])
	{
		vector<P> res = dfs(i);
		vector<ll> t(2010);
		for (auto& p1 : now)
		{
			for (auto& p2 : res) {
				if (p1.first + p2.first > 2000)continue;
				t[p1.first + p2.first] += p1.second * p2.second % mod;
				t[p1.first + p2.first] %= mod;
			}
		}
		vector<P> ne;
		REP(i, 2010) {
			if (t[i] > 0)ne.push_back(P(i, t[i]));
		}
		now = ne;
		//cout << a << " " << now.size() << endl;
	}
	return now;
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	ll n, k;
	cin >> n >> k;
	REP(i, n)cin >> v[i];
	REP(i, n - 1) {
		cin >> p[i + 1];
		p[i + 1]--;
		g[p[i + 1]].push_back(i + 1);
	}
	vector<P> ans = dfs(0);
	REP(i, ans.size()) {
		//cout << i << " " << ans[i].first << " " << ans[i].second << endl;
		if (ans[i].first == k) {
			cout << ans[i].second << endl;
			return 0;
		}
	}
	cout << 0 << endl;
	return 0;
}
accuracy: 0.038461538461538464
time_ms: 40
memory_kb: 5376
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
#define rep(i,a,b) for (int i=(int)(a);i<(int)(b);i++)
#define all(p) p.begin(),p.end()

#include <atcoder/convolution>
using mint = atcoder::modint998244353;

void solve();
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t = 1;
    // cin >> t;
    rep(i, 0, t) solve();
}

void solve(){
    int N, K;
    cin >> N >> K;
    vector dp(N, vector<mint>(K + 1));
    vector<int> A(N);
    rep(i, 0, N) cin >> A[i];
    vector<vector<int>> G(N);
    rep(i, 1, N){
        int a;
        cin >> a;
        G[a - 1].push_back(i);
    }
    for (int i = N - 1; i >= 0; i--){
        if (A[i] <= K) dp[i][A[i]] = 1;
        for (auto x : G[i]){
            dp[i] = atcoder::convolution(dp[i], dp[x]);
            dp[i].resize(K + 1);
        }
        dp[i][0] += 1;
    }
    cout << dp[0][K].val() << "\n";
}
accuracy: 1
time_ms: 170
memory_kb: 30208
final_rank: 12

code_snippet: #include <bits/extc++.h>

#include <atcoder/convolution>
#include <atcoder/modint>

using ll = long long;

using mint = atcoder::modint998244353;

int main() {
  int N, K;
  std::cin >> N >> K;
  std::vector<int> A(N);
  for (auto& a : A) {
    std::cin >> a;
  }

  std::vector nanachi(N, std::vector<int>());

  for (int i = 1; i < N; i++) {
    int p;
    std::cin >> p;

    p--;

    nanachi[i].push_back(p);
    nanachi[p].push_back(i);
  }

  std::vector snuke(N, std::vector<mint>(K + 1));

  auto rec = [&](auto&& rec, int v, int p = -1) -> void {
    std::vector<mint> tmp(K + 1);

    tmp[0] = 1;

    for (int w : nanachi[v]) {
      if (w == p) continue;

      rec(rec, w, v);

      tmp = atcoder::convolution(tmp, snuke[w]);

      tmp.resize(K + 1);
    }

    std::vector<mint> res(K + 1);

    res[0] = 1;

    for (int i = 0; i <= K - A[v]; i++) {
      res[i + A[v]] = tmp[i];
    }

    snuke[v] = std::move(res);
  };

  rec(rec, 0);

  std::cout << snuke[0][K].val() << std::endl;
}
accuracy: 1
time_ms: 180
memory_kb: 18048
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for(ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

#define TT template<typename T>
TT using vec = vector<T>;
template<class T1, class T2> bool chmin(T1 &x, T2 y) { return x > y ? (x = y, true) : false; }
template<class T1, class T2> bool chmax(T1 &x, T2 y) { return x < y ? (x = y, true) : false; }

struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

/*
@brief テンプレート
*/

#include<atcoder/modint>
#include<atcoder/convolution>
using mint=atcoder::modint998244353;

int main(){
    int N,K;
    cin>>N>>K;
    vector<int>A(N);
    for(int i=0;i<N;i++)cin>>A[i];
    vector<vector<int>>G(N);
    for(int i=1;i<N;i++){
        int p;
        cin>>p;
        p--;
        G[i].push_back(p);
        G[p].push_back(i);
    }
    vector<vector<mint>>V(N);
    auto dfs=[&](auto dfs,int x,int p)-> void {
        V[x].resize(K+1);
        if(A[x]<=K)V[x][A[x]]=1;
        for(auto i:G[x]){
            if(i==p)continue;
            dfs(dfs,i,x);
            V[x]=atcoder::convolution(V[x],V[i]);
            while(V[x].size()>K+1)V[x].pop_back();
        }
        V[x][0]=1;
    };
    dfs(dfs,0,-1);
    cout<<V[0][K].val()<<"\n";
}
accuracy: 1
time_ms: 170
memory_kb: 26880
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for(ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

#define TT template<typename T>
TT using vec = vector<T>;
template<class T1, class T2> bool chmin(T1 &x, T2 y) { return x > y ? (x = y, true) : false; }
template<class T1, class T2> bool chmax(T1 &x, T2 y) { return x < y ? (x = y, true) : false; }

struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

/*
@brief テンプレート
*/

#include<atcoder/modint>
#include<atcoder/convolution>
using mint=atcoder::modint998244353;

int main(){
    int N,K;
    cin>>N>>K;
    vector<int>A(N);
    for(int i=0;i<N;i++)cin>>A[i];
    vector<vector<int>>G(N);
    for(int i=1;i<N;i++){
        int p;
        cin>>p;
        p--;
        G[i].push_back(p);
        G[p].push_back(i);
    }
    vector<vector<mint>>V(N);
    auto dfs=[&](auto dfs,int x,int p)-> void {
        V[x].resize(K+1);
        V[x][0]=1;
        if(A[x]<=K)V[x][A[x]]=1;
        for(auto i:G[x]){
            if(i==p)continue;
            dfs(dfs,i,x);
            V[x]=atcoder::convolution(V[x],V[i]);
            while(V[x].size()>K+1)V[x].pop_back();
        }
    };
    dfs(dfs,0,-1);
    cout<<V[0][K].val()<<"\n";
}
accuracy: 0.038461538461538464
time_ms: 100
memory_kb: 16256
final_rank: 19

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

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
#define rep3(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define ov4(a, b, c, d, name, ...) name
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for (ll i = (a) - 1; i >= (b); i--)
#define fore(e, v) for (auto&& e : v)
#define all(a) begin(a), end(a)
#define sz(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template <typename T, typename S>
bool chmin(T& a, const S& b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S>
bool chmax(T& a, const S& b) {
  return a < b ? a = b, 1 : 0;
}
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
#define i128 __int128_t
struct _ {
  _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

constexpr int mod = 998244353;
struct mint {
  int x;
  mint(ll x_ = 0) : x(x_ % mod) {
    if (x < 0) x += mod;
  }
  mint operator-() {
    auto res = *this;
    res.x = (x ? mod - x : 0);
    return res;
  }
  mint& operator+=(mint r) {
    if ((x += r.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(mint r) {
    if ((x -= r.x) < 0) x += mod;
    return *this;
  }
  mint& operator*=(mint r) {
    x = 1LL * x * r.x % mod;
    return *this;
  }
  mint& operator/=(mint r) { return *this *= r.inv(); }
  friend mint operator+(mint a, mint b) { return a += b; }
  friend mint operator-(mint a, mint b) { return a -= b; }
  friend mint operator*(mint a, mint b) { return a *= b; }
  friend mint operator/(mint a, mint b) { return a /= b; }
  mint inv() const { return pow(mod - 2); }
  mint pow(ll b) const {
    mint a = *this, c = 1;
    while (b) {
      if (b & 1) c *= a;
      a *= a;
      b >>= 1;
    }
    return c;
  }
};
using vm = vector<mint>;

mint g = 3;  // 原始根
void fft(vm& a, bool inv = false) {
  int n = sz(a), s = __lg(n);
  static vm z, iz;
  while (sz(z) <= s) {
    z.eb(g.pow(mint(-1).x / (1 << sz(z))));
    iz.eb(z.back().inv());
  }
  vm b(n);
  rep(i, 1, s + 1) {
    int w = 1 << s - i;
    mint base = inv ? iz[i] : z[i], now = 1;
    for (int y = 0; y < n / 2; y += w) {
      rep(x, w) {
        auto l = a[y << 1 | x], r = now * a[y << 1 | x | w];
        b[y | x] = l + r, b[y | x | n >> 1] = l - r;
      }
      now *= base;
    }
    swap(a, b);
  }
}  // 247a8873
vm mul(vm a, vm b) {
  int n = sz(a), m = sz(b);
  if (!n or !m) return {};
  if (min(n, m) <= 30) {
    vm ans(n + m - 1);
    rep(i, n) rep(j, m) ans[i + j] += a[i] * b[j];
    return ans;
  }
  int N = n + m - 1;
  int z = bit_ceil(unsigned(N));
  a.resize(z), b.resize(z);
  fft(a), fft(b);
  rep(i, z) a[i] *= b[i];
  fft(a, true);
  a.resize(n + m - 1);
  mint iz = mint(z).inv();
  fore(e, a) e *= iz;
  return a;
}  // 6ee9c185

int main() {
  int N,K;
  cin>>N>>K;
  const int MAX_K=2001;
  vector<vm> dp(N,vm(MAX_K));
  vi A(N),P(N);
  fore(i,A)cin>>i;
  rep(i,1,N)cin>>P[i],--P[i];
  rep(i,N)dp[i][0]=1;
  per(i,N,0){
    vm d(MAX_K);
    rep(j,MAX_K)if(j+A[i]<MAX_K)d[j+A[i]]=dp[i][j];
    d[0]=1;
    dp[i]=d;
    if(i==0)break;
    auto v=mul(dp[P[i]],dp[i]);
    rep(j,MAX_K)dp[P[i]][j]=v[j];
  }
  cout<<dp[0][K].x<<'\n';
}
accuracy: 1
time_ms: 310
memory_kb: 19328
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, a, b) for (int i = a; i < (b); i++)
#define all(a) (a).begin(), (a).end()

const ll mod = 998244353;
struct mm {
   ll x;
   mm(ll x_ = 0) : x(x_ % mod) {
      if(x < 0) x += mod;
   }
   friend mm operator+(mm a, mm b) { return a.x + b.x; }
   friend mm operator-(mm a, mm b) { return a.x - b.x; }
   friend mm operator*(mm a, mm b) { return a.x * b.x; }
   friend mm operator/(mm a, mm b) { return a * b.inv(); }
   // 4 行コピペ  Alt + Shift + クリックで複数カーソル
   friend mm& operator+=(mm& a, mm b) { return a = a.x + b.x; }
   friend mm& operator-=(mm& a, mm b) { return a = a.x - b.x; }
   friend mm& operator*=(mm& a, mm b) { return a = a.x * b.x; }
   friend mm& operator/=(mm& a, mm b) { return a = a * b.inv(); }
   mm inv() const { return pow(mod - 2); }
   mm pow(ll b) const {
      mm a = *this, c = 1;
      while(b) {
         if(b & 1) c *= a;
         a *= a;
         b >>= 1;
      }
      return c;
   }
};

// {998244353, 3}, {754974721, 11}, {167772161, 3}, {469762049, 3}, {2130706433, 3}
mm g = 3;  // 原始根
void fft(vector<mm>& a) {
   ll n = a.size(), lg = __lg(n);
   static auto z = [] {
      vector<mm> z(30);
      mm s = 1;
      for(int i = 2; i < 32; i++) {
         z[i - 2] = s * g.pow(mod >> i);
         s *= g.inv().pow(mod >> i);
      }
      return z;
   }();
   rep(l, 0, lg) {
      ll w = 1 << (lg - l - 1);
      mm s = 1;
      rep(k, 0, 1 << l) {
         ll o = k << (lg - l);
         for(int i = o; i < o + w; i++) {
            mm x = a[i], y = a[i + w] * s;
            a[i] = x + y;
            a[i + w] = x - y;
         }
         s *= z[countr_zero<uint64_t>(~k)];
      }
   }
}
// コピペ
void ifft(vector<mm>& a) {
   ll n = a.size(), lg = __lg(n);
   static auto z = [] {
      vector<mm> z(30);
      mm s = 1;
      for(int i = 2; i < 32; i++) {  // g を逆数に
         z[i - 2] = s * g.inv().pow(mod >> i);
         s *= g.pow(mod >> i);
      }
      return z;
   }();
   for(ll l = lg; l--;) {  // 逆順に
      ll w = 1 << (lg - l - 1);
      mm s = 1;
      rep(k, 0, 1 << l) {
         ll o = k << (lg - l);
         for(int i = o; i < o + w; i++) {
            mm x = a[i], y = a[i + w];  // *s を移動
            a[i] = x + y;
            a[i + w] = (x - y) * s;
         }
         s *= z[countr_zero<uint64_t>(~k)];
      }
   }
}
vector<mm> conv(vector<mm> a, vector<mm> b) {
   if(a.empty() || b.empty()) return {};
   size_t n_ = a.size() + b.size() - 1, n = bit_ceil(n_);
   // if(min(sz(a), sz(b)) <= 60) 愚直に掛け算
   a.resize(n);
   b.resize(n);
   fft(a);
   fft(b);
   mm x = mm(n).inv();
   rep(i, 0, n) a[i] *= b[i] * x;
   ifft(a);
   a.resize(n_);
   return a;
}


int main(){
    int n,k;
    cin >> n >> k;
    vector<int> a(n);
    vector<vector<int>> graph(n);
    rep(i, 0, n) {
        cin >> a[i];
    }
    rep(i, 1, n){
        int x;
        cin >> x;
        x--;
        graph[x].push_back(i);
    }
    vector<vector<mm>> vs(n, vector<mm>(k+1, 0));
    rep(i, 0, n){
        if(a[i] <= k) vs[i][a[i]] = 1;
    }

    auto dfs = [&](auto dfs, int now) -> vector<mm> {
        vector<mm> nw = vs[now];
        for(auto to: graph[now]){
            nw = conv(nw, dfs(dfs, to));
            nw.resize(k+1);
        }
        nw[0] = 1;

        return nw;
    };

    cout << dfs(dfs, 0)[k].x << endl;
}
accuracy: 1
time_ms: 450
memory_kb: 32384
final_rank: 14

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

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
#define rep3(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define ov4(a, b, c, d, name, ...) name
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for (ll i = (a) - 1; i >= (b); i--)
#define fore(e, v) for (auto&& e : v)
#define all(a) begin(a), end(a)
#define sz(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template <typename T, typename S>
bool chmin(T& a, const S& b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S>
bool chmax(T& a, const S& b) {
  return a < b ? a = b, 1 : 0;
}
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
#define i128 __int128_t
struct _ {
  _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

constexpr int mod = 998244353;
struct mint {
  int x;
  mint(ll x_ = 0) : x(x_ % mod) {
    if (x < 0) x += mod;
  }
  mint operator-() {
    auto res = *this;
    res.x = (x ? mod - x : 0);
    return res;
  }
  mint& operator+=(mint r) {
    if ((x += r.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(mint r) {
    if ((x -= r.x) < 0) x += mod;
    return *this;
  }
  mint& operator*=(mint r) {
    x = 1LL * x * r.x % mod;
    return *this;
  }
  mint& operator/=(mint r) { return *this *= r.inv(); }
  friend mint operator+(mint a, mint b) { return a += b; }
  friend mint operator-(mint a, mint b) { return a -= b; }
  friend mint operator*(mint a, mint b) { return a *= b; }
  friend mint operator/(mint a, mint b) { return a /= b; }
  mint inv() const { return pow(mod - 2); }
  mint pow(ll b) const {
    mint a = *this, c = 1;
    while (b) {
      if (b & 1) c *= a;
      a *= a;
      b >>= 1;
    }
    return c;
  }
};
using vm = vector<mint>;

mint g = 3;  // 原始根
void fft(vm& a, bool inv = false) {
  int n = sz(a), s = __lg(n);
  static vm z, iz;
  while (sz(z) <= s) {
    z.eb(g.pow(mint(-1).x / (1 << sz(z))));
    iz.eb(z.back().inv());
  }
  vm b(n);
  rep(i, 1, s + 1) {
    int w = 1 << s - i;
    mint base = inv ? iz[i] : z[i], now = 1;
    for (int y = 0; y < n / 2; y += w) {
      rep(x, w) {
        auto l = a[y << 1 | x], r = now * a[y << 1 | x | w];
        b[y | x] = l + r, b[y | x | n >> 1] = l - r;
      }
      now *= base;
    }
    swap(a, b);
  }
}  // 247a8873
vm mul(vm a, vm b) {
  int n = sz(a), m = sz(b);
  if (!n or !m) return {};
  if (min(n, m) <= 30) {
    vm ans(n + m - 1);
    rep(i, n) rep(j, m) ans[i + j] += a[i] * b[j];
    return ans;
  }
  int N = n + m - 1;
  int z = bit_ceil(unsigned(N));
  a.resize(z), b.resize(z);
  fft(a), fft(b);
  rep(i, z) a[i] *= b[i];
  fft(a, true);
  a.resize(n + m - 1);
  mint iz = mint(z).inv();
  fore(e, a) e *= iz;
  return a;
}  // 6ee9c185

int main() {
  int N,K;
  cin>>N>>K;
  const int MAX_K=2001;
  vector<vm> dp(N,vm(MAX_K));
  vi A(N),P(N);
  fore(i,A)cin>>i;
  rep(i,1,N)cin>>P[i],--P[i];
  rep(i,N)dp[i][0]=1,dp[i][A[i]]=1;
  per(i,N,0){
    if(i==0)break;
    auto v=mul(dp[P[i]],dp[i]);
    rep(j,MAX_K)dp[P[i]][j]=v[j];
  }
  cout<<dp[0][K].x<<'\n';
}
accuracy: 0.038461538461538464
time_ms: 190
memory_kb: 13056
final_rank: 18

code_snippet: #line 2 "/Users/noya2/Desktop/Noya2_library/template/template.hpp"
using namespace std;

#include<bits/stdc++.h>
#line 1 "/Users/noya2/Desktop/Noya2_library/template/inout_old.hpp"
namespace noya2 {

template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p){
    os << p.first << " " << p.second;
    return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p){
    is >> p.first >> p.second;
    return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v){
    int s = (int)v.size();
    for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
    return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v){
    for (auto &x : v) is >> x;
    return is;
}

void in() {}
template <typename T, class... U>
void in(T &t, U &...u){
    cin >> t;
    in(u...);
}

void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u){
    cout << t;
    if (sizeof...(u)) cout << sep;
    out(u...);
}

template<typename T>
void out(const vector<vector<T>> &vv){
    int s = (int)vv.size();
    for (int i = 0; i < s; i++) out(vv[i]);
}

struct IoSetup {
    IoSetup(){
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
        cerr << fixed << setprecision(7);
    }
} iosetup_noya2;

} // namespace noya2
#line 1 "/Users/noya2/Desktop/Noya2_library/template/const.hpp"
namespace noya2{

const int iinf = 1'000'000'007;
const long long linf = 2'000'000'000'000'000'000LL;
const long long mod998 =  998244353;
const long long mod107 = 1000000007;
const long double pi = 3.14159265358979323;
const vector<int> dx = {0,1,0,-1,1,1,-1,-1};
const vector<int> dy = {1,0,-1,0,1,-1,-1,1};
const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string alp = "abcdefghijklmnopqrstuvwxyz";
const string NUM = "0123456789";

void yes(){ cout << "Yes\n"; }
void no(){ cout << "No\n"; }
void YES(){ cout << "YES\n"; }
void NO(){ cout << "NO\n"; }
void yn(bool t){ t ? yes() : no(); }
void YN(bool t){ t ? YES() : NO(); }

} // namespace noya2
#line 2 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp"

#line 6 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp"

namespace noya2{

unsigned long long inner_binary_gcd(unsigned long long a, unsigned long long b){
    if (a == 0 || b == 0) return a + b;
    int n = __builtin_ctzll(a); a >>= n;
    int m = __builtin_ctzll(b); b >>= m;
    while (a != b) {
        int mm = __builtin_ctzll(a - b);
        bool f = a > b;
        unsigned long long c = f ? a : b;
        b = f ? b : a;
        a = (c - b) >> mm;
    }
    return a << std::min(n, m);
}

template<typename T> T gcd_fast(T a, T b){ return static_cast<T>(inner_binary_gcd(std::abs(a),std::abs(b))); }

long long sqrt_fast(long long n) {
    if (n <= 0) return 0;
    long long x = sqrt(n);
    while ((x + 1) * (x + 1) <= n) x++;
    while (x * x > n) x--;
    return x;
}

template<typename T> T floor_div(const T n, const T d) {
    assert(d != 0);
    return n / d - static_cast<T>((n ^ d) < 0 && n % d != 0);
}

template<typename T> T ceil_div(const T n, const T d) {
    assert(d != 0);
    return n / d + static_cast<T>((n ^ d) >= 0 && n % d != 0);
}

template<typename T> void uniq(std::vector<T> &v){
    std::sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
}

template <typename T, typename U> inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; }

template <typename T, typename U> inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; }

template<typename T> inline bool range(T l, T x, T r){ return l <= x && x < r; }

} // namespace noya2
#line 8 "/Users/noya2/Desktop/Noya2_library/template/template.hpp"

#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define repp(i,m,n) for (int i = (m); i < (int)(n); i++)
#define reb(i,n) for (int i = (int)(n-1); i >= 0; i--)
#define all(v) (v).begin(),(v).end()

using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pil = pair<int,ll>;
using pli = pair<ll,int>;

namespace noya2{

/*　~ (. _________ . /)　*/

}

using namespace noya2;


#line 2 "c.cpp"

#line 2 "/Users/noya2/Desktop/Noya2_library/tree/simple_tree.hpp"

#line 2 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"

#line 4 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"
#include<ranges>
#line 7 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"

namespace noya2::internal {

template<class E>
struct csr {
    csr () {}
    csr (int _n) : n(_n) {}
    csr (int _n, int m) : n(_n){
        start.reserve(m);
        elist.reserve(m);
    }
    // ACL style constructor (do not have to call build)
    csr (int _n, const std::vector<std::pair<int,E>> &idx_elem) : n(_n), start(_n + 2), elist(idx_elem.size()) {
        for (auto &[i, e] : idx_elem){
            start[i + 2]++;
        }
        for (int i = 1; i < n; i++){
            start[i + 2] += start[i + 1];
        }
        for (auto &[i, e] : idx_elem){
            elist[start[i + 1]++] = e;
        }
        prepared = true;
    }
    int add(int idx, E elem){
        int eid = start.size();
        start.emplace_back(idx);
        elist.emplace_back(elem);
        return eid;
    }
    void build(){
        if (prepared) return ;
        int m = start.size();
        std::vector<E> nelist(m);
        std::vector<int> nstart(n + 2, 0);
        for (int i = 0; i < m; i++){
            nstart[start[i] + 2]++;
        }
        for (int i = 1; i < n; i++){
            nstart[i + 2] += nstart[i + 1];
        }
        for (int i = 0; i < m; i++){
            nelist[nstart[start[i] + 1]++] = elist[i];
        }
        swap(elist,nelist);
        swap(start,nstart);
        prepared = true;
    }
    const auto operator[](int idx) const {
        return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);
    }
    auto operator[](int idx){
        return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);
    }
    const auto operator()(int idx, int l, int r) const {
        return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);
    }
    auto operator()(int idx, int l, int r){
        return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);
    }
    size_t size() const {
        return n;
    }
    int n;
    std::vector<int> start;
    std::vector<E> elist;
    bool prepared = false;
};

} // namespace noya2::internal
#line 5 "/Users/noya2/Desktop/Noya2_library/tree/simple_tree.hpp"

namespace noya2 {

struct simple_tree {
    internal::csr<int> g;
    simple_tree () {}
    simple_tree (int _n) : g(_n, (_n - 1)*2) {
        if (_n == 1){
            g.build();
        }
    }
    void add_edge(int u, int v){
        g.add(u, v);
        int id = g.add(v, u);
        if (id + 1 == (g.n - 1)*2) g.build();
    }
    void input(int indexed = 1){
        for (int i = 0; i < g.n - 1; i++){
            int u, v; cin >> u >> v;
            u -= indexed, v -= indexed;
            add_edge(u, v);
        }
    }
    void input_parents(int indexed = 1){
        for (int i = 0; i < g.n - 1; i++){
            int v; cin >> v;
            v -= indexed;
            add_edge(i + 1, v);
        }
    }
    const auto operator[](int v) const {
        return g[v];
    }
    auto operator[](int v){
        return g[v];
    }
    size_t size() const {
        return g.size();
    }
};

} // namespace noya2
#line 4 "c.cpp"

#include<atcoder/modint>
using mint = atcoder::modint998244353;
#include<atcoder/convolution>

void solve(){
    int n, k; in(n,k);
    vector<int> a(n); in(a);
    simple_tree g(n);
    rep(i,n-1){
        int p; in(p); p--;
        g.add_edge(i+1,p);
    }
    auto dfs = [&](auto sfs, int v, int f) -> vector<mint> {
        vector<mint> dp = {1};
        for (int u : g[v]){
            if (u == f) continue;
            auto ep = sfs(sfs,u,v);
            int dsz = dp.size();
            int esz = ep.size();
            auto ndp = atcoder::convolution(dp,ep);
            if ((int)ndp.size() > k+1){
                ndp.resize(k+1);
            }
            ndp.resize(k+1);
            swap(dp,ndp);
        }
        dp.insert(dp.begin(),a[v],0);
        dp[0] = 1;
        if ((int)(dp.size()) > k+1){
            dp.resize(k+1);
        }
        return dp;
    };
    auto dp = dfs(dfs,0,-1);
    dp.resize(k+1);
    out(dp[k].val());
}

int main(){
    int t = 1; //in(t);
    while (t--) { solve(); }
}
accuracy: 1
time_ms: 80
memory_kb: 3840
final_rank: 1

code_snippet: // AOJ #3281 Infinite Problems
// 2025.2.18

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 998244353;
 
int N, K;
vector<int> a;
vector<vector<int>> children;
 
vector<int> dfs(int u) {
    vector<int> poly(K+1, 0);
    if(a[u] <= K) poly[a[u]] = 1;
    
    for (int v : children[u]) {
        vector<int> childPoly = dfs(v);
        vector<int> newPoly(K+1, 0);
        for (int i = 0; i <= K; i++) newPoly[i] = (newPoly[i] + poly[i]) % MOD;
        for (int i = 0; i <= K; i++) {
            if(poly[i] != 0){
                for (int j = 0; j <= K - i; j++){
                    if(childPoly[j] != 0)
                        newPoly[i+j] = (newPoly[i+j] + (ll) poly[i] * childPoly[j]) % MOD;
                }
            }
        }
        poly = move(newPoly);
    }
    return poly;
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    cin >> N >> K;
    a.resize(N+1);
    for (int i = 1; i <= N; i++) cin >> a[i];
    children.assign(N+1, vector<int>());
    for (int i = 2; i <= N; i++){
        int p;
        cin >> p;
        children[p].push_back(i);
    }
    vector<int> dp = dfs(1);
    cout << dp[K] % MOD << endl;
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 3644
final_rank: 2

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

template <int mod>
struct static_modint {
    using mint = static_modint;
    int x;

    static_modint() : x(0) {}
    static_modint(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    mint& operator+=(const mint& rhs) {
        if ((x += rhs.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        if ((x += mod - rhs.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        x = (int) (1LL * x * rhs.x % mod);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint pow(long long n) const {
        mint _x = *this, r = 1;
        while (n) {
            if (n & 1) r *= _x;
            _x *= _x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const { return pow(mod - 2); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }
    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs.x == rhs.x;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs.x != rhs.x;
    }

    friend ostream &operator<<(ostream &os, const mint &p) {
        return os << p.x;
    }
    friend istream &operator>>(istream &is, mint &a) {
        int64_t t; is >> t;
        a = static_modint<mod>(t);
        return (is);
    }
};

const unsigned int mod = 998244353;
using modint = static_modint<mod>;
modint mod_pow(ll n, ll x) { return modint(n).pow(x); }
modint mod_pow(modint n, ll x) { return n.pow(x); }

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

constexpr int countr_zero_constexpr(unsigned int n) {
    int x = 0;
    while (!(n & (1 << x))) x++;
    return x;
}

struct fft_info {
    int g;
    static constexpr int rank2 = countr_zero_constexpr(mod - 1);
    std::array<modint, rank2 + 1> root;   // root[i]^(2^i) == 1
    std::array<modint, rank2 + 1> iroot;  // root[i] * iroot[i] == 1

    std::array<modint, std::max(0, rank2 - 2 + 1)> rate2;
    std::array<modint, std::max(0, rank2 - 2 + 1)> irate2;

    std::array<modint, std::max(0, rank2 - 3 + 1)> rate3;
    std::array<modint, std::max(0, rank2 - 3 + 1)> irate3;

    fft_info() {
        g = primitive_root<mod>;
        root[rank2] = (mod_pow(g, (mod - 1) >> rank2));
        iroot[rank2] = root[rank2].inv();
        for (int i = rank2 - 1; i >= 0; i--) {
            root[i] = root[i + 1] * root[i + 1];
            iroot[i] = iroot[i + 1] * iroot[i + 1];
        }

        {
            modint prod = 1, iprod = 1;
            for (int i = 0; i <= rank2 - 2; i++) {
                rate2[i] = root[i + 2] * prod;
                irate2[i] = iroot[i + 2] * iprod;
                prod *= iroot[i + 2];
                iprod *= root[i + 2];
            }
        }
        {
            modint prod = 1, iprod = 1;
            for (int i = 0; i <= rank2 - 3; i++) {
                rate3[i] = root[i + 3] * prod;
                irate3[i] = iroot[i + 3] * iprod;
                prod *= iroot[i + 3];
                iprod *= root[i + 3];
            }
        }
    }
};

void butterfly(vector<modint> &a) {
    int n = int(a.size());
    int h = __builtin_ctz(n);

    static const fft_info info;
    int len = 0;  // a[i, i+(n>>len), i+2*(n>>len), ..] is transformed
    while (len < h) {
        if (h - len == 1) {
            int pp = 1 << (h - len - 1);
            modint rot = 1;
            for (int s = 0; s < (1 << len); s++) {
                int offset = s << (h - len);
                for (int i = 0; i < pp; i++) {
                    auto l = a[i + offset];
                    auto r = a[i + offset + pp] * rot;
                    a[i + offset] = l + r;
                    a[i + offset + pp] = l - r;
                }
                if (s + 1 != (1 << len))
                    rot *= info.rate2[__builtin_ctz(~(unsigned int)(s))];
            }
            len++;
        } else {
            // 4-base
            int pp = 1 << (h - len - 2);
            modint rot = 1, imag = info.root[2];
            for (int s = 0; s < (1 << len); s++) {
                modint rot2 = rot * rot;
                modint rot3 = rot2 * rot;
                int offset = s << (h - len);
                for (int i = 0; i < pp; i++) {
                    auto mod2 = 1ULL * mod * mod;
                    auto a0 = 1ULL * a[i + offset].x;
                    auto a1 = 1ULL * a[i + offset + pp].x * rot.x;
                    auto a2 = 1ULL * a[i + offset + 2 * pp].x * rot2.x;
                    auto a3 = 1ULL * a[i + offset + 3 * pp].x * rot3.x;
                    auto a1na3imag =
                            1ULL * modint(a1 + mod2 - a3).x * imag.x;
                    auto na2 = mod2 - a2;
                    a[i + offset] = a0 + a2 + a1 + a3;
                    a[i + offset + 1 * pp] = a0 + a2 + (2 * mod2 - (a1 + a3));
                    a[i + offset + 2 * pp] = a0 + na2 + a1na3imag;
                    a[i + offset + 3 * pp] = a0 + na2 + (mod2 - a1na3imag);
                }
                if (s + 1 != (1 << len))
                    rot *= info.rate3[__builtin_ctz(~(unsigned int)(s))];
            }
            len += 2;
        }
    }
}

void butterfly_inv(vector<modint> &a) {
    int n = int(a.size());
    int h = __builtin_ctz(n);

    static const fft_info info;
    int len = h; // a[i, i+(n>>len), i+2*(n>>len), ..] is transformed
    while (len) {
        if (len == 1) {
            int pp = 1 << (h - len);
            modint irot = 1;
            for (int s = 0; s < (1 << (len - 1)); s++) {
                int offset = s << (h - len + 1);
                for (int i = 0; i < pp; i++) {
                    auto l = a[i + offset];
                    auto r = a[i + offset + pp];
                    a[i + offset] = l + r;
                    a[i + offset + pp] =
                            (unsigned long long)(mod + l.x - r.x) *
                            irot.x;
                }
                if (s + 1 != (1 << (len - 1)))
                    irot *= info.irate2[__builtin_ctz(~(unsigned int)(s))];
            }
            len--;
        } else {
            // 4-base
            int pp = 1 << (h - len);
            modint irot = 1, iimag = info.iroot[2];
            for (int s = 0; s < (1 << (len - 2)); s++) {
                modint irot2 = irot * irot;
                modint irot3 = irot2 * irot;
                int offset = s << (h - len + 2);
                for (int i = 0; i < pp; i++) {
                    auto a0 = 1ULL * a[i + offset + 0 * pp].x;
                    auto a1 = 1ULL * a[i + offset + 1 * pp].x;
                    auto a2 = 1ULL * a[i + offset + 2 * pp].x;
                    auto a3 = 1ULL * a[i + offset + 3 * pp].x;

                    auto a2na3iimag = 1ULL * modint((mod + a2 - a3) * iimag.x).x;

                    a[i + offset] = a0 + a1 + a2 + a3;
                    a[i + offset + 1 * pp] =
                            (a0 + (mod - a1) + a2na3iimag) * irot.x;
                    a[i + offset + 2 * pp] =
                            (a0 + a1 + (mod - a2) + (mod - a3)) *
                            irot2.x;
                    a[i + offset + 3 * pp] =
                            (a0 + (mod - a1) + (mod - a2na3iimag)) *
                            irot3.x;
                }
                if (s + 1 != (1 << (len - 2)))
                    irot *= info.irate3[__builtin_ctz(~(unsigned int)(s))];
            }
            len -= 2;
        }
    }
}

vector<modint> convolution_naive(const vector<modint>& a, const vector<modint>& b) {
    int n = int(a.size()), m = int(b.size());
    vector<modint> res(n + m - 1);
    if (n < m) {
        for (int j = 0; j < m; ++j) {
            for (int i = 0; i < n; ++i) {
                res[i + j] += a[i] * b[j];
            }
        }
    } else {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                res[i + j] += a[i] * b[j];
            }
        }
    }
    return res;
}

vector<modint> convolution_fft(vector<modint>& a, vector<modint>& b) {
    int n = int(a.size()), m = int(b.size());
    int z = 1;
    while (z < n + m - 1) z *= 2;
    a.resize(z);
    butterfly(a);
    b.resize(z);
    butterfly(b);
    for (int i = 0; i < z; ++i) {
        a[i] *= b[i];
    }
    butterfly_inv(a);
    a.resize(n + m - 1);
    modint iz = modint(z).inv();
    for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
    return a;
}

template <class T>
vector<T> convolution(const vector<T>& a, const vector<T>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n or !m) return {};

    int z = 1;
    while (z < n + m - 1) z *= 2;
    assert((mod - 1) % z == 0);

    vector<modint> a2(n), b2(m);
    for (int i = 0; i < n; ++i) {
        a2[i] = modint(a[i]);
    }
    for (int i = 0; i < m; ++i) {
        b2[i] = modint(b[i]);
    }

    vector<T> c(n + m - 1);
    vector<modint> c2;

    if (min(n,m) <= 60) c2 = convolution_naive(a2, b2);
    else c2 = convolution_fft(a2, b2);

    for (int i = 0; i < n + m - 1; ++i) {
        c[i] = c2[i].x;
    }
    return c;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,k; cin >> n >> k;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    vector<vector<int>> g(n);
    for (int i = 1; i < n; ++i) {
        int p; cin >> p; p--;
        g[p].push_back(i);
    }
    auto dfs = [&](auto dfs,int s) -> vector<modint> {
        vector<modint> res(k+1);
        if (a[s] <= k) res[a[s]] = 1;
        for (int t : g[s]) {
            auto r = dfs(dfs,t);
            res = convolution(res, r);
            res.resize(k+1);
        }
        res[0] = 1;
        return res;
    };
    auto res = dfs(dfs,0);
    cout << res[k] << endl;
}
accuracy: 1
time_ms: 270
memory_kb: 3668
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define repl(i, l, r) for (int i = (l); i < (int)(r); ++i)
#define rep(i, n) repl(i, 0, n)
#define CST(x) cout << fixed << setprecision(x)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
using ll = long long;
constexpr ll MOD = 998244353;
constexpr int inf = 1e9 + 10;
constexpr ll INF = (ll)4e18 + 10;
constexpr int dx[9] = {1, 0, -1, 0, 1, -1, -1, 1, 0};
constexpr int dy[9] = {0, 1, 0, -1, 1, 1, -1, -1, 0};
const double PI = acos(-1);
template <typename T>
using MaxHeap = priority_queue<T>;
template <typename T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;
template <typename T>
inline bool chmax(T& a, T b) {
    return ((a < b) ? (a = b, true) : (false));
}
template <typename T>
inline bool chmin(T& a, T b) {
    return ((a > b) ? (a = b, true) : (false));
}
template <typename T>
inline void yn(const T& a) {
    ((a) ? (cout << "Yes" << endl) : (cout << "No" << endl));
}
template <typename T>
inline void YN(const T& a) {
    ((a) ? (cout << "YES" << endl) : (cout << "NO" << endl));
}
namespace internal {
#ifndef _MSC_VER
template <class T>
using is_signed_int128 = typename std::conditional<std::is_same<T, __int128_t>::value ||
                                                       std::is_same<T, __int128>::value,
                                                   std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int128 = typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                                         std::is_same<T, unsigned __int128>::value,
                                                     std::true_type, std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value, __uint128_t, unsigned __int128>;

template <class T>
using is_integral =
    typename std::conditional<std::is_integral<T>::value || is_signed_int128<T>::value ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_signed_int =
    typename std::conditional<(internal::is_integral<T>::value && std::is_signed<T>::value) ||
                                  is_signed_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value && std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value, make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value, std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T>
using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int = typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                                                std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value && std::is_unsigned<T>::value, std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value, std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
template <class T>
using to_unsigned_t = typename to_unsigned<T>::type;
}  // namespace internal
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}
struct barrett {
    unsigned int _m;
    unsigned long long im;

    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x = (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n>
constexpr bool is_prime = is_prime_constexpr(n);
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}
struct modint_base {};
struct static_modint_base : modint_base {};
template <class T>
using is_modint = std::is_base_of<modint_base, T>;
template <class T>
using is_modint_t = std::enable_if_t<is_modint<T>::value>;
template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : static_modint_base {
    using mint = static_modint;

   public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; }
    friend mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; }
    friend mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; }
    friend mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; }
    friend bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; }
    friend bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; }

   private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = is_prime<m>;
};
template <int id>
struct dynamic_modint : modint_base {
    using mint = dynamic_modint;

   public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; }
    friend mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; }
    friend mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; }
    friend mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; }
    friend bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; }
    friend bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; }

   private:
    unsigned int _v;
    static barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id>
barrett dynamic_modint<id>::bt = 998244353;
using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;
template <class T>
using is_static_modint = std::is_base_of<static_modint_base, T>;
template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;
template <class>
struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};
template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;
using mint = modint998244353;
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m>
constexpr int primitive_root = primitive_root_constexpr(m);
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}
template <class mint, is_static_modint_t<mint>* = nullptr>
void butterfly(std::vector<mint>& a) {
    static constexpr int g = primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = ceil_pow2(n);

    static bool first = true;
    static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i <= cnt2 - 2; i++) {
            sum_e[i] = es[i] * now;
            now *= ies[i];
        }
    }
    for (int ph = 1; ph <= h; ph++) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint now = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p] * now;
                a[i + offset] = l + r;
                a[i + offset + p] = l - r;
            }
            now *= sum_e[bsf(~(unsigned int)(s))];
        }
    }
}
template <class mint, is_static_modint_t<mint>* = nullptr>
void butterfly_inv(std::vector<mint>& a) {
    static constexpr int g = primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = ceil_pow2(n);

    static bool first = true;
    static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i <= cnt2 - 2; i++) {
            sum_ie[i] = ies[i] * now;
            now *= es[i];
        }
    }

    for (int ph = h; ph >= 1; ph--) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint inow = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p];
                a[i + offset] = l + r;
                a[i + offset + p] =
                    (unsigned long long)(mint::mod() + l.val() - r.val()) * inow.val();
            }
            inow *= sum_ie[bsf(~(unsigned int)(s))];
        }
    }
}
template <class mint, is_static_modint_t<mint>* = nullptr>
std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};
    if (std::min(n, m) <= 60) {
        if (n < m) {
            std::swap(n, m);
            std::swap(a, b);
        }
        std::vector<mint> ans(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                ans[i + j] += a[i] * b[j];
            }
        }
        return ans;
    }
    int z = 1 << ceil_pow2(n + m - 1);
    a.resize(z);
    butterfly(a);
    b.resize(z);
    butterfly(b);
    for (int i = 0; i < z; i++) {
        a[i] *= b[i];
    }
    butterfly_inv(a);
    a.resize(n + m - 1);
    mint iz = mint(z).inv();
    for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
    return a;
}

template <unsigned int mod = 998244353, class T, std::enable_if_t<is_integral<T>::value>* = nullptr>
std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    using mint = static_modint<mod>;
    std::vector<mint> a2(n), b2(m);
    for (int i = 0; i < n; i++) {
        a2[i] = mint(a[i]);
    }
    for (int i = 0; i < m; i++) {
        b2[i] = mint(b[i]);
    }
    auto c2 = convolution(move(a2), move(b2));
    std::vector<T> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        c[i] = c2[i].val();
    }
    return c;
}
std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                      const std::vector<long long>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    static constexpr unsigned long long MOD1 = 754974721;  // 2^24
    static constexpr unsigned long long MOD2 = 167772161;  // 2^25
    static constexpr unsigned long long MOD3 = 469762049;  // 2^26
    static constexpr unsigned long long M2M3 = MOD2 * MOD3;
    static constexpr unsigned long long M1M3 = MOD1 * MOD3;
    static constexpr unsigned long long M1M2 = MOD1 * MOD2;
    static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;

    static constexpr unsigned long long i1 = inv_gcd(MOD2 * MOD3, MOD1).second;
    static constexpr unsigned long long i2 = inv_gcd(MOD1 * MOD3, MOD2).second;
    static constexpr unsigned long long i3 = inv_gcd(MOD1 * MOD2, MOD3).second;

    auto c1 = convolution<MOD1>(a, b);
    auto c2 = convolution<MOD2>(a, b);
    auto c3 = convolution<MOD3>(a, b);

    std::vector<long long> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        unsigned long long x = 0;
        x += (c1[i] * i1) % MOD1 * M2M3;
        x += (c2[i] * i2) % MOD2 * M1M3;
        x += (c3[i] * i3) % MOD3 * M1M2;
        long long diff = c1[i] - safe_mod((long long)(x), (long long)(MOD1));
        if (diff < 0) diff += MOD1;
        static constexpr unsigned long long offset[5] = {0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
        x -= offset[diff % 5];
        c[i] = x;
    }

    return c;
}
int main() {
    cin.tie(nullptr);
    cout.tie(nullptr);
    ios::sync_with_stdio(false);

    int n, k;
    cin >> n >> k;
    vector a(n, 0);
    rep(i, n) cin >> a[i];
    vector<vector<int>> G(n);
    repl(i, 1, n) {
        int p;
        cin >> p;
        G[p - 1].emplace_back(i);
    }

    auto f = [&a, &G, &k](auto self, const int& v) -> vector<mint> {
        vector<mint> res(a[v] + 1);
        res[a[v]] = 1;
        for (const auto& to : G[v]) {
            res = convolution(res, self(self, to));
            res.resize(k + 1);
        }
        res[0] = 1;
        return res;
    };

    vector<mint> ans = f(f, 0);

    cout << ans[k].val() << endl;

    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 3768
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define repl(i, l, r) for (int i = (l); i < (int)(r); ++i)
#define rep(i, n) repl(i, 0, n)
#define CST(x) cout << fixed << setprecision(x)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
using ll = long long;
constexpr ll MOD = 998244353;
constexpr int inf = 1e9 + 10;
constexpr ll INF = (ll)4e18 + 10;
constexpr int dx[9] = {1, 0, -1, 0, 1, -1, -1, 1, 0};
constexpr int dy[9] = {0, 1, 0, -1, 1, 1, -1, -1, 0};
const double PI = acos(-1);
template <typename T>
using MaxHeap = priority_queue<T>;
template <typename T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;
template <typename T>
inline bool chmax(T& a, T b) {
    return ((a < b) ? (a = b, true) : (false));
}
template <typename T>
inline bool chmin(T& a, T b) {
    return ((a > b) ? (a = b, true) : (false));
}
template <typename T>
inline void yn(const T& a) {
    ((a) ? (cout << "Yes" << endl) : (cout << "No" << endl));
}
template <typename T>
inline void YN(const T& a) {
    ((a) ? (cout << "YES" << endl) : (cout << "NO" << endl));
}
namespace internal {
#ifndef _MSC_VER
template <class T>
using is_signed_int128 = typename std::conditional<std::is_same<T, __int128_t>::value ||
                                                       std::is_same<T, __int128>::value,
                                                   std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int128 = typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                                         std::is_same<T, unsigned __int128>::value,
                                                     std::true_type, std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value, __uint128_t, unsigned __int128>;

template <class T>
using is_integral =
    typename std::conditional<std::is_integral<T>::value || is_signed_int128<T>::value ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_signed_int =
    typename std::conditional<(internal::is_integral<T>::value && std::is_signed<T>::value) ||
                                  is_signed_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value && std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value, make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value, std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T>
using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int = typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                                                std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value && std::is_unsigned<T>::value, std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value, std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
template <class T>
using to_unsigned_t = typename to_unsigned<T>::type;
}  // namespace internal
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}
struct barrett {
    unsigned int _m;
    unsigned long long im;

    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x = (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n>
constexpr bool is_prime = is_prime_constexpr(n);
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}
struct modint_base {};
struct static_modint_base : modint_base {};
template <class T>
using is_modint = std::is_base_of<modint_base, T>;
template <class T>
using is_modint_t = std::enable_if_t<is_modint<T>::value>;
template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : static_modint_base {
    using mint = static_modint;

   public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; }
    friend mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; }
    friend mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; }
    friend mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; }
    friend bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; }
    friend bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; }

   private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = is_prime<m>;
};
template <int id>
struct dynamic_modint : modint_base {
    using mint = dynamic_modint;

   public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) { return mint(lhs) += rhs; }
    friend mint operator-(const mint& lhs, const mint& rhs) { return mint(lhs) -= rhs; }
    friend mint operator*(const mint& lhs, const mint& rhs) { return mint(lhs) *= rhs; }
    friend mint operator/(const mint& lhs, const mint& rhs) { return mint(lhs) /= rhs; }
    friend bool operator==(const mint& lhs, const mint& rhs) { return lhs._v == rhs._v; }
    friend bool operator!=(const mint& lhs, const mint& rhs) { return lhs._v != rhs._v; }

   private:
    unsigned int _v;
    static barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id>
barrett dynamic_modint<id>::bt = 998244353;
using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;
template <class T>
using is_static_modint = std::is_base_of<static_modint_base, T>;
template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;
template <class>
struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};
template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;
using mint = modint998244353;
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m>
constexpr int primitive_root = primitive_root_constexpr(m);
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}
template <class mint, is_static_modint_t<mint>* = nullptr>
void butterfly(std::vector<mint>& a) {
    static constexpr int g = primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = ceil_pow2(n);

    static bool first = true;
    static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i <= cnt2 - 2; i++) {
            sum_e[i] = es[i] * now;
            now *= ies[i];
        }
    }
    for (int ph = 1; ph <= h; ph++) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint now = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p] * now;
                a[i + offset] = l + r;
                a[i + offset + p] = l - r;
            }
            now *= sum_e[bsf(~(unsigned int)(s))];
        }
    }
}
template <class mint, is_static_modint_t<mint>* = nullptr>
void butterfly_inv(std::vector<mint>& a) {
    static constexpr int g = primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = ceil_pow2(n);

    static bool first = true;
    static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i <= cnt2 - 2; i++) {
            sum_ie[i] = ies[i] * now;
            now *= es[i];
        }
    }

    for (int ph = h; ph >= 1; ph--) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint inow = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p];
                a[i + offset] = l + r;
                a[i + offset + p] =
                    (unsigned long long)(mint::mod() + l.val() - r.val()) * inow.val();
            }
            inow *= sum_ie[bsf(~(unsigned int)(s))];
        }
    }
}
template <class mint, is_static_modint_t<mint>* = nullptr>
std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};
    if (std::min(n, m) <= 60) {
        if (n < m) {
            std::swap(n, m);
            std::swap(a, b);
        }
        std::vector<mint> ans(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                ans[i + j] += a[i] * b[j];
            }
        }
        return ans;
    }
    int z = 1 << ceil_pow2(n + m - 1);
    a.resize(z);
    butterfly(a);
    b.resize(z);
    butterfly(b);
    for (int i = 0; i < z; i++) {
        a[i] *= b[i];
    }
    butterfly_inv(a);
    a.resize(n + m - 1);
    mint iz = mint(z).inv();
    for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
    return a;
}

template <unsigned int mod = 998244353, class T, std::enable_if_t<is_integral<T>::value>* = nullptr>
std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    using mint = static_modint<mod>;
    std::vector<mint> a2(n), b2(m);
    for (int i = 0; i < n; i++) {
        a2[i] = mint(a[i]);
    }
    for (int i = 0; i < m; i++) {
        b2[i] = mint(b[i]);
    }
    auto c2 = convolution(move(a2), move(b2));
    std::vector<T> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        c[i] = c2[i].val();
    }
    return c;
}
std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                      const std::vector<long long>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    static constexpr unsigned long long MOD1 = 754974721;  // 2^24
    static constexpr unsigned long long MOD2 = 167772161;  // 2^25
    static constexpr unsigned long long MOD3 = 469762049;  // 2^26
    static constexpr unsigned long long M2M3 = MOD2 * MOD3;
    static constexpr unsigned long long M1M3 = MOD1 * MOD3;
    static constexpr unsigned long long M1M2 = MOD1 * MOD2;
    static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;

    static constexpr unsigned long long i1 = inv_gcd(MOD2 * MOD3, MOD1).second;
    static constexpr unsigned long long i2 = inv_gcd(MOD1 * MOD3, MOD2).second;
    static constexpr unsigned long long i3 = inv_gcd(MOD1 * MOD2, MOD3).second;

    auto c1 = convolution<MOD1>(a, b);
    auto c2 = convolution<MOD2>(a, b);
    auto c3 = convolution<MOD3>(a, b);

    std::vector<long long> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        unsigned long long x = 0;
        x += (c1[i] * i1) % MOD1 * M2M3;
        x += (c2[i] * i2) % MOD2 * M1M3;
        x += (c3[i] * i3) % MOD3 * M1M2;
        long long diff = c1[i] - safe_mod((long long)(x), (long long)(MOD1));
        if (diff < 0) diff += MOD1;
        static constexpr unsigned long long offset[5] = {0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
        x -= offset[diff % 5];
        c[i] = x;
    }

    return c;
}
int main() {
    cin.tie(nullptr);
    cout.tie(nullptr);
    ios::sync_with_stdio(false);

    int n, k;
    cin >> n >> k;
    vector a(n, 0);
    rep(i, n) cin >> a[i];
    vector<vector<int>> G(n);
    repl(i, 1, n) {
        int p;
        cin >> p;
        G[p - 1].emplace_back(i);
    }

    auto f = [&a, &G, &k](auto self, const int& v) -> vector<mint> {
        vector<mint> res(a[v] + 1);
        res[0] = res[a[v]] = 1;
        for (const auto& to : G[v]) {
            res = convolution(res, self(self, to));
            res.resize(k + 1);
        }
        return res;
    };

    vector<mint> ans = f(f, 0);

    cout << ans[k].val() << endl;

    return 0;
}
accuracy: 0.038461538461538464
time_ms: 40
memory_kb: 3560
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 1000000007
#define EPS 0.000000001


#define MOD 998244353
#define SIZE 2005

vector<int> G[SIZE];
ll N,K;
ll A[SIZE];
ll dp[SIZE][SIZE];

void rec(ll node){

	//答えない
	dp[node][0] = 1; //■葉方向のノードは自分の正解を前提としているので、自分含め葉方向の和は0

	if(A[node] <= K){ //答える

		vector<ll> work(SIZE,0);

		dp[node][A[node]] = 1;

		for(int i = 0; i < G[node].size(); i++){ //逐次子をマージしていく

			int child = G[node][i];
			rec(child); //■子を先に処理

			for(int now = 0; now <= K; now++){
				for(int next = 0; now+next <= K; next++){

					work[now+next] += (dp[node][now]*dp[child][next])%MOD;
					work[now+next] %= MOD;
				}
			}
			for(int a = 0; a <= K; a++){

				dp[node][a] = work[a];
				work[a] = 0;
			}
		}
	}
}

int main(){

	scanf("%lld %lld",&N,&K);

	for(ll i = 0; i < N; i++){

		scanf("%lld",&A[i]);
	}

	int pre;
	for(int i = 1; i < N; i++){

		scanf("%d",&pre);
		pre--;

		G[pre].push_back(i);
	}

	rec(0);

	/*for(int i = 0; i <= K; i++){

		printf("dp[0][%d]:%lld\n",i,dp[0][i]);
	}*/

	printf("%lld\n",(dp[0][K]));

	return 0;
}
accuracy: 0.038461538461538464
time_ms: 1550
memory_kb: 13792
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <int mod>
class Modint {
    using mint = Modint;
    static_assert(mod > 0, "Modulus must be positive");

public:
    static constexpr int get_mod() noexcept { return mod; }

    constexpr Modint(long long y = 0) noexcept : x(y >= 0 ? y % mod : (y % mod + mod) % mod) {}

    constexpr int value() const noexcept { return x; }

    constexpr mint& operator+=(const mint& r) noexcept { if ((x += r.x) >= mod) x -= mod; return *this; }
    constexpr mint& operator-=(const mint& r) noexcept { if ((x += mod - r.x) >= mod) x -= mod; return *this; }
    constexpr mint& operator*=(const mint& r) noexcept { x = static_cast<int>(1LL * x * r.x % mod); return *this; }
    constexpr mint& operator/=(const mint& r) noexcept { *this *= r.inv(); return *this; }

    constexpr mint operator-() const noexcept { return mint(-x); }

    constexpr mint operator+(const mint& r) const noexcept { return mint(*this) += r; }
    constexpr mint operator-(const mint& r) const noexcept { return mint(*this) -= r; }
    constexpr mint operator*(const mint& r) const noexcept { return mint(*this) *= r; }
    constexpr mint operator/(const mint& r) const noexcept { return mint(*this) /= r; }

    constexpr bool operator==(const mint& r) const noexcept { return x == r.x; }
    constexpr bool operator!=(const mint& r) const noexcept { return x != r.x; }

    constexpr mint inv() const noexcept {
        int a = x, b = mod, u = 1, v = 0;
        while (b > 0) {
            int t = a / b;
            std::swap(a -= t * b, b);
            std::swap(u -= t * v, v);
        }
        return mint(u);
    }

    constexpr mint pow(long long n) const noexcept {
        mint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend std::ostream& operator<<(std::ostream& os, const mint& r) {
        return os << r.x;
    }

    friend std::istream& operator>>(std::istream& is, mint& r) {
        long long t;
        is >> t;
        r = mint(t);
        return is;
    }

private:
    int x;
};

using mint = Modint<998244353>;

constexpr int get_primitive_root(int mod) {
    if (mod == 167772161) return 3;
    if (mod == 469762049) return 3;
    if (mod == 754974721) return 11;
    if (mod == 998244353) return 3;
    if (mod == 1224736769) return 3;
}

template <typename T>
void bit_reverse(std::vector<T>& a) {
    int n = a.size();
    for (int i = 0, j = 1; j < n - 1; ++j) {
        for (int k = n >> 1; k > (i ^= k); k >>= 1);
        if (i < j) std::swap(a[i], a[j]);
    }
}

template <typename mint>
void ntt(std::vector<mint>& a, bool ordered = true) {
    constexpr int mod = mint::get_mod();
    constexpr mint primitive_root = get_primitive_root(mod);

    int n = a.size();
    for (int m = n; m > 1; m >>= 1) {
        mint omega = primitive_root.pow((mod - 1) / m);
        for (int s = 0; s < n / m; ++s) {
            mint w = 1;
            for (int i = 0; i < m / 2; ++i) {
                mint l = a[s * m + i];
                mint r = a[s * m + i + m / 2];
                a[s * m + i] = l + r;
                a[s * m + i + m / 2] = (l - r) * w;
                w *= omega;
            }
        }
    }
    if (ordered) bit_reverse(a);
}

template <typename mint>
void intt(std::vector<mint>& a, bool ordered = true) {
    constexpr int mod = mint::get_mod();
    constexpr mint primitive_root = get_primitive_root(mod);

    if (ordered) bit_reverse(a);
    int n = a.size();
    for (int m = 2; m <= n; m <<= 1) {
        mint omega = primitive_root.pow((mod - 1) / m).inv();
        for (int s = 0; s < n / m; ++s) {
            mint w = 1;
            for (int i = 0; i < m / 2; ++i) {
                mint l = a[s * m + i];
                mint r = a[s * m + i + m / 2] * w;
                a[s * m + i] = l + r;
                a[s * m + i + m / 2] = l - r;
                w *= omega;
            }
        }
    }
}

template <typename mint>
std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
    int size = a.size() + b.size() - 1;
    int n = 1;
    while (n < size) n <<= 1;
    a.resize(n);
    b.resize(n);
    ntt(a, false);
    ntt(b, false);
    for (int i = 0; i < n; ++i) a[i] *= b[i];
    intt(a, false);
    a.resize(size);
    mint n_inv = mint(n).inv();
    for (int i = 0; i < size; ++i) a[i] *= n_inv;
    return a;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int N, K;
    cin >> N >> K;
    vector<int> a(N), p(N);
    for (auto& x : a) cin >> x;
    vector<vector<int>> G(N);
    rep(i,1,N) {
        int p;
        cin >> p;
        --p;
        G[p].push_back(i);
    }
    vector<vector<mint>> dp(N, vector<mint>(K+1));

    auto dfs = [&](auto& dfs, int v) -> void {
        if (a[v] > K) return;
        dp[v][a[v]] = 1;
        for (int c : G[v]) {
            dfs(dfs, c);
            dp[c][0] += 1;
            dp[v] = convolution(dp[v], dp[c]);
            dp[v].resize(K+1);
        }
    };

    dfs(dfs, 0);
    cout << dp[0][K] << endl;
}
accuracy: 1
time_ms: 490
memory_kb: 29740
final_rank: 13

code_snippet: #include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <deque>
#include <forward_list>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using lint = long long;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios { fast_ios(){ cin.tie(nullptr), ios::sync_with_stdio(false), cout << fixed << setprecision(20); }; } fast_ios_;
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)
template <typename T, typename V>
void ndarray(vector<T>& vec, const V& val, int len) { vec.assign(len, val); }
template <typename T, typename V, typename... Args> void ndarray(vector<T>& vec, const V& val, int len, Args... args) { vec.resize(len), for_each(begin(vec), end(vec), [&](T& v) { ndarray(v, val, args...); }); }
template <typename T> bool chmax(T &m, const T q) { return m < q ? (m = q, true) : false; }
template <typename T> bool chmin(T &m, const T q) { return m > q ? (m = q, true) : false; }
int floor_lg(long long x) { return x <= 0 ? -1 : 63 - __builtin_clzll(x); }
template <typename T1, typename T2> pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first + r.first, l.second + r.second); }
template <typename T1, typename T2> pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first - r.first, l.second - r.second); }
template <typename T> vector<T> sort_unique(vector<T> vec) { sort(vec.begin(), vec.end()), vec.erase(unique(vec.begin(), vec.end()), vec.end()); return vec; }
template <typename T> int arglb(const std::vector<T> &v, const T &x) { return std::distance(v.begin(), std::lower_bound(v.begin(), v.end(), x)); }
template <typename T> int argub(const std::vector<T> &v, const T &x) { return std::distance(v.begin(), std::upper_bound(v.begin(), v.end(), x)); }
template <typename T> istream &operator>>(istream &is, vector<T> &vec) { for (auto &v : vec) is >> v; return is; }
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) { os << '['; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <typename T, size_t sz> ostream &operator<<(ostream &os, const array<T, sz> &arr) { os << '['; for (auto v : arr) os << v << ','; os << ']'; return os; }
#if __cplusplus >= 201703L
template <typename... T> istream &operator>>(istream &is, tuple<T...> &tpl) { std::apply([&is](auto &&... args) { ((is >> args), ...);}, tpl); return is; }
template <typename... T> ostream &operator<<(ostream &os, const tuple<T...> &tpl) { os << '('; std::apply([&os](auto &&... args) { ((os << args << ','), ...);}, tpl); return os << ')'; }
#endif
template <typename T> ostream &operator<<(ostream &os, const deque<T> &vec) { os << "deq["; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <typename T> ostream &operator<<(ostream &os, const set<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T, typename TH> ostream &operator<<(ostream &os, const unordered_set<T, TH> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T> ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &pa) { os << '(' << pa.first << ',' << pa.second << ')'; return os; }
template <typename TK, typename TV> ostream &operator<<(ostream &os, const map<TK, TV> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
template <typename TK, typename TV, typename TH> ostream &operator<<(ostream &os, const unordered_map<TK, TV, TH> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
#ifdef HITONANODE_LOCAL
const string COLOR_RESET = "\033[0m", BRIGHT_GREEN = "\033[1;32m", BRIGHT_RED = "\033[1;31m", BRIGHT_CYAN = "\033[1;36m", NORMAL_CROSSED = "\033[0;9;37m", RED_BACKGROUND = "\033[1;41m", NORMAL_FAINT = "\033[0;2m";
#define dbg(x) cerr << BRIGHT_CYAN << #x << COLOR_RESET << " = " << (x) << NORMAL_FAINT << " (L" << __LINE__ << ") " << __FILE__ << COLOR_RESET << endl
#define dbgif(cond, x) ((cond) ? cerr << BRIGHT_CYAN << #x << COLOR_RESET << " = " << (x) << NORMAL_FAINT << " (L" << __LINE__ << ") " << __FILE__ << COLOR_RESET << endl : cerr)
#else
#define dbg(x) (x)
#define dbgif(cond, x) 0
#endif

template <int md> struct ModInt {
#if __cplusplus >= 201402L
#define MDCONST constexpr
#else
#define MDCONST
#endif
    using lint = long long;
    MDCONST static int mod() { return md; }
    static int get_primitive_root() {
        static int primitive_root = 0;
        if (!primitive_root) {
            primitive_root = [&]() {
                std::set<int> fac;
                int v = md - 1;
                for (lint i = 2; i * i <= v; i++)
                    while (v % i == 0) fac.insert(i), v /= i;
                if (v > 1) fac.insert(v);
                for (int g = 1; g < md; g++) {
                    bool ok = true;
                    for (auto i : fac)
                        if (ModInt(g).pow((md - 1) / i) == 1) {
                            ok = false;
                            break;
                        }
                    if (ok) return g;
                }
                return -1;
            }();
        }
        return primitive_root;
    }
    int val;
    MDCONST ModInt() : val(0) {}
    MDCONST ModInt &_setval(lint v) { return val = (v >= md ? v - md : v), *this; }
    MDCONST ModInt(lint v) { _setval(v % md + md); }
    MDCONST explicit operator bool() const { return val != 0; }
    MDCONST ModInt operator+(const ModInt &x) const { return ModInt()._setval((lint)val + x.val); }
    MDCONST ModInt operator-(const ModInt &x) const {
        return ModInt()._setval((lint)val - x.val + md);
    }
    MDCONST ModInt operator*(const ModInt &x) const {
        return ModInt()._setval((lint)val * x.val % md);
    }
    MDCONST ModInt operator/(const ModInt &x) const {
        return ModInt()._setval((lint)val * x.inv() % md);
    }
    MDCONST ModInt operator-() const { return ModInt()._setval(md - val); }
    MDCONST ModInt &operator+=(const ModInt &x) { return *this = *this + x; }
    MDCONST ModInt &operator-=(const ModInt &x) { return *this = *this - x; }
    MDCONST ModInt &operator*=(const ModInt &x) { return *this = *this * x; }
    MDCONST ModInt &operator/=(const ModInt &x) { return *this = *this / x; }
    friend MDCONST ModInt operator+(lint a, const ModInt &x) {
        return ModInt()._setval(a % md + x.val);
    }
    friend MDCONST ModInt operator-(lint a, const ModInt &x) {
        return ModInt()._setval(a % md - x.val + md);
    }
    friend MDCONST ModInt operator*(lint a, const ModInt &x) {
        return ModInt()._setval(a % md * x.val % md);
    }
    friend MDCONST ModInt operator/(lint a, const ModInt &x) {
        return ModInt()._setval(a % md * x.inv() % md);
    }
    MDCONST bool operator==(const ModInt &x) const { return val == x.val; }
    MDCONST bool operator!=(const ModInt &x) const { return val != x.val; }
    MDCONST bool operator<(const ModInt &x) const {
        return val < x.val;
    } // To use std::map<ModInt, T>
    friend std::istream &operator>>(std::istream &is, ModInt &x) {
        lint t;
        return is >> t, x = ModInt(t), is;
    }
    MDCONST friend std::ostream &operator<<(std::ostream &os, const ModInt &x) {
        return os << x.val;
    }
    MDCONST ModInt pow(lint n) const {
        ModInt ans = 1, tmp = *this;
        while (n) {
            if (n & 1) ans *= tmp;
            tmp *= tmp, n >>= 1;
        }
        return ans;
    }

    static std::vector<ModInt> facs, facinvs, invs;
    MDCONST static void _precalculation(int N) {
        int l0 = facs.size();
        if (N > md) N = md;
        if (N <= l0) return;
        facs.resize(N), facinvs.resize(N), invs.resize(N);
        for (int i = l0; i < N; i++) facs[i] = facs[i - 1] * i;
        facinvs[N - 1] = facs.back().pow(md - 2);
        for (int i = N - 2; i >= l0; i--) facinvs[i] = facinvs[i + 1] * (i + 1);
        for (int i = N - 1; i >= l0; i--) invs[i] = facinvs[i] * facs[i - 1];
    }
    MDCONST lint inv() const {
        if (this->val < std::min(md >> 1, 1 << 21)) {
            while (this->val >= int(facs.size())) _precalculation(facs.size() * 2);
            return invs[this->val].val;
        } else {
            return this->pow(md - 2).val;
        }
    }
    MDCONST ModInt fac() const {
        while (this->val >= int(facs.size())) _precalculation(facs.size() * 2);
        return facs[this->val];
    }
    MDCONST ModInt facinv() const {
        while (this->val >= int(facs.size())) _precalculation(facs.size() * 2);
        return facinvs[this->val];
    }
    MDCONST ModInt doublefac() const {
        lint k = (this->val + 1) / 2;
        return (this->val & 1) ? ModInt(k * 2).fac() / (ModInt(2).pow(k) * ModInt(k).fac())
                               : ModInt(k).fac() * ModInt(2).pow(k);
    }
    MDCONST ModInt nCr(const ModInt &r) const {
        return (this->val < r.val) ? 0 : this->fac() * (*this - r).facinv() * r.facinv();
    }
    MDCONST ModInt nPr(const ModInt &r) const {
        return (this->val < r.val) ? 0 : this->fac() * (*this - r).facinv();
    }

    ModInt sqrt() const {
        if (val == 0) return 0;
        if (md == 2) return val;
        if (pow((md - 1) / 2) != 1) return 0;
        ModInt b = 1;
        while (b.pow((md - 1) / 2) == 1) b += 1;
        int e = 0, m = md - 1;
        while (m % 2 == 0) m >>= 1, e++;
        ModInt x = pow((m - 1) / 2), y = (*this) * x * x;
        x *= (*this);
        ModInt z = b.pow(m);
        while (y != 1) {
            int j = 0;
            ModInt t = y;
            while (t != 1) j++, t *= t;
            z = z.pow(1LL << (e - j - 1));
            x *= z, z *= z, y *= z;
            e = j;
        }
        return ModInt(std::min(x.val, md - x.val));
    }
};
template <int md> std::vector<ModInt<md>> ModInt<md>::facs = {1};
template <int md> std::vector<ModInt<md>> ModInt<md>::facinvs = {1};
template <int md> std::vector<ModInt<md>> ModInt<md>::invs = {0};
using mint = ModInt<998244353>;


// Integer convolution for arbitrary mod
// with NTT (and Garner's algorithm) for ModInt / ModIntRuntime class.
// We skip Garner's algorithm if `skip_garner` is true or mod is in `nttprimes`.
// input: a (size: n), b (size: m)
// return: vector (size: n + m - 1)
template <typename MODINT>
std::vector<MODINT> nttconv(std::vector<MODINT> a, std::vector<MODINT> b, bool skip_garner);

constexpr int nttprimes[3] = {998244353, 167772161, 469762049};

// Integer FFT (Fast Fourier Transform) for ModInt class
// (Also known as Number Theoretic Transform, NTT)
// is_inverse: inverse transform
// ** Input size must be 2^n **
template <typename MODINT> void ntt(std::vector<MODINT> &a, bool is_inverse = false) {
    int n = a.size();
    if (n == 1) return;
    static const int mod = MODINT::mod();
    static const MODINT root = MODINT::get_primitive_root();
    assert(__builtin_popcount(n) == 1 and (mod - 1) % n == 0);

    static std::vector<MODINT> w{1}, iw{1};
    for (int m = w.size(); m < n / 2; m *= 2) {
        MODINT dw = root.pow((mod - 1) / (4 * m)), dwinv = 1 / dw;
        w.resize(m * 2), iw.resize(m * 2);
        for (int i = 0; i < m; i++) w[m + i] = w[i] * dw, iw[m + i] = iw[i] * dwinv;
    }

    if (!is_inverse) {
        for (int m = n; m >>= 1;) {
            for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
                for (int i = s; i < s + m; i++) {
                    MODINT x = a[i], y = a[i + m] * w[k];
                    a[i] = x + y, a[i + m] = x - y;
                }
            }
        }
    } else {
        for (int m = 1; m < n; m *= 2) {
            for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
                for (int i = s; i < s + m; i++) {
                    MODINT x = a[i], y = a[i + m];
                    a[i] = x + y, a[i + m] = (x - y) * iw[k];
                }
            }
        }
        int n_inv = MODINT(n).inv();
        for (auto &v : a) v *= n_inv;
    }
}
template <int MOD>
std::vector<ModInt<MOD>> nttconv_(const std::vector<int> &a, const std::vector<int> &b) {
    int sz = a.size();
    assert(a.size() == b.size() and __builtin_popcount(sz) == 1);
    std::vector<ModInt<MOD>> ap(sz), bp(sz);
    for (int i = 0; i < sz; i++) ap[i] = a[i], bp[i] = b[i];
    ntt(ap, false);
    if (a == b)
        bp = ap;
    else
        ntt(bp, false);
    for (int i = 0; i < sz; i++) ap[i] *= bp[i];
    ntt(ap, true);
    return ap;
}
long long garner_ntt_(int r0, int r1, int r2, int mod) {
    using mint2 = ModInt<nttprimes[2]>;
    static const long long m01 = 1LL * nttprimes[0] * nttprimes[1];
    static const long long m0_inv_m1 = ModInt<nttprimes[1]>(nttprimes[0]).inv();
    static const long long m01_inv_m2 = mint2(m01).inv();

    int v1 = (m0_inv_m1 * (r1 + nttprimes[1] - r0)) % nttprimes[1];
    auto v2 = (mint2(r2) - r0 - mint2(nttprimes[0]) * v1) * m01_inv_m2;
    return (r0 + 1LL * nttprimes[0] * v1 + m01 % mod * v2.val) % mod;
}
template <typename MODINT>
std::vector<MODINT> nttconv(std::vector<MODINT> a, std::vector<MODINT> b, bool skip_garner) {
    if (a.empty() or b.empty()) return {};
    int sz = 1, n = a.size(), m = b.size();
    while (sz < n + m) sz <<= 1;
    if (sz <= 16) {
        std::vector<MODINT> ret(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) ret[i + j] += a[i] * b[j];
        }
        return ret;
    }
    int mod = MODINT::mod();
    if (skip_garner or
        std::find(std::begin(nttprimes), std::end(nttprimes), mod) != std::end(nttprimes)) {
        a.resize(sz), b.resize(sz);
        if (a == b) {
            ntt(a, false);
            b = a;
        } else {
            ntt(a, false), ntt(b, false);
        }
        for (int i = 0; i < sz; i++) a[i] *= b[i];
        ntt(a, true);
        a.resize(n + m - 1);
    } else {
        std::vector<int> ai(sz), bi(sz);
        for (int i = 0; i < n; i++) ai[i] = a[i].val;
        for (int i = 0; i < m; i++) bi[i] = b[i].val;
        auto ntt0 = nttconv_<nttprimes[0]>(ai, bi);
        auto ntt1 = nttconv_<nttprimes[1]>(ai, bi);
        auto ntt2 = nttconv_<nttprimes[2]>(ai, bi);
        a.resize(n + m - 1);
        for (int i = 0; i < n + m - 1; i++)
            a[i] = garner_ntt_(ntt0[i].val, ntt1[i].val, ntt2[i].val, mod);
    }
    return a;
}

template <typename MODINT>
std::vector<MODINT> nttconv(const std::vector<MODINT> &a, const std::vector<MODINT> &b) {
    return nttconv<MODINT>(a, b, false);
}


int main() {
    int N, K;
    cin >> N >> K;
    vector<int> A(N);
    cin >> A;
    vector<vector<int>> child(N);
    FOR(i, 1, N) {
        int p;
        cin >> p;
        --p;
        child[p].push_back(i);
    }
    dbg(A);
    dbg(child);

    auto rec = [&](auto &&self, int now) -> vector<mint> {
        vector<mint> ret{1};
        for (auto nxt : child[now]) {
            auto sol = self(self, nxt);
            ret = nttconv(ret, sol);
            if (int(ret.size()) > K + 1) ret.resize(K + 1);
        }
        std::vector<mint> emp(A[now]);
        ret.insert(ret.begin(), emp.begin(), emp.end());
        ret[0] = 1;
        if (int(ret.size()) > K + 1) ret.resize(K + 1);
        return ret;
    };

    auto ret = rec(rec, 0);
    cout << (K < int(ret.size()) ? ret[K] : 0) << '\n';
}
accuracy: 1
time_ms: 180
memory_kb: 3816
final_rank: 5

code_snippet: /**
 *   @FileName	a.cpp
 *   @Author	kanpurin
 *   @Created	2022.03.19 19:31:43
**/

#include "bits/stdc++.h" 
using namespace std; 
typedef long long ll;


template< int MOD >
struct mint {
public:
    unsigned int x;
    mint() : x(0) {}
    mint(long long v) {
        long long w = (long long)(v % (long long)(MOD));
        if (w < 0) w += MOD;
        x = (unsigned int)(w);
    }
    mint(std::string &s) {
        unsigned int z = 0;
        for (int i = 0; i < s.size(); i++) {
            z *= 10;
            z += s[i] - '0';
            z %= MOD;
        }
        x = z;
    }
    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }
    mint& operator+=(const mint &a) {
        if ((x += a.x) >= MOD) x -= MOD;
        return *this;
    }
    mint& operator-=(const mint &a) {
        if ((x -= a.x) >= MOD) x += MOD;
        return *this;
    }
    mint& operator*=(const mint &a) {
        unsigned long long z = x;
        z *= a.x;
        x = (unsigned int)(z % MOD);
        return *this;
    }
    mint& operator/=(const mint &a) {return *this = *this * a.inv(); }
    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs.x == rhs.x;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs.x != rhs.x;
    }
    friend std::ostream& operator<<(std::ostream &os, const mint &n) {
        return os << n.x;
    }
    friend std::istream &operator>>(std::istream &is, mint &n) {
        unsigned int x;
        is >> x;
        n = mint(x);
        return is;
    }
    mint inv() const {
        assert(x);
        return pow(MOD-2);
    }
    mint pow(long long n) const {        
        assert(0 <= n);
        mint p = *this, r = 1;
        while (n) {
            if (n & 1) r *= p;
            p *= p;
            n >>= 1;
        }
        return r;
    }
    
    mint sqrt() const {
        if (this->x < 2) return *this;
        if (this->pow((MOD-1)>>1).x != 1) return mint(0);
        mint b = 1, one = 1;
        while (b.pow((MOD-1) >> 1) == 1) b += one;
        long long m = MOD-1, e = 0;
        while (m % 2 == 0) m >>= 1, e += 1;
        mint x = this->pow((m - 1) >> 1);
        mint y = (*this) * x * x;
        x *= (*this);
        mint z = b.pow(m);
        while (y.x != 1) {
            int j = 0;
            mint t = y;
            while (t != one) j += 1, t *= t;
            z = z.pow(1LL << (e-j-1));
            x *= z; z *= z; y *= z; e = j;
        }
        return x;
    }
};

constexpr int MOD = 998244353;

template < const int MOD , bool any = false>
struct FormalPowerSeries {
private:
    using FPS = FormalPowerSeries<MOD,any>;

    void ntt(bool inverse) {
        static bool first = true;
        static mint<MOD> dw[30], idw[30];
        if (first) {
            first = false;
            mint<MOD> root = 2;
            while (root.pow((MOD - 1) / 2) == 1) root += 1;
            for (int i = 0; i < 30; i++) dw[i] = -root.pow((MOD - 1) >> (i + 2)), idw[i] = mint<MOD>(1) / dw[i];
        }
        int n = this->size();
        assert((n & (n - 1)) == 0);
        if (not inverse) {
            for (int m = n; m >>= 1;) {
                mint<MOD> w = 1;
                for (int s = 0, k = 0; s < n; s += 2 * m) {
                    for (int i = s, j = s + m; i < s + m; i++, j++) {
                        auto x = this->a[i], y = this->a[j]*w;
                        if (x.x >= MOD) x.x -= MOD;
                        this->a[i].x = x.x + y.x, this->a[j].x = x.x+(MOD-y.x);
                    }
                    w *= dw[__builtin_ctz(++k)];
                }
            }
        } else {
            for (int m = 1; m < n; m *= 2) {
                mint<MOD> w = 1;
                for (int s = 0, k = 0; s < n; s += 2 * m) {
                    for (int i = s, j = s + m; i < s + m; i++, j++) {
                        auto x = this->a[i], y = this->a[j];
                        this->a[i] = x+y, this->a[j].x = x.x+(MOD-y.x), this->a[j] *= w;
                    }
                    w *= idw[__builtin_ctz(++k)];
                }
            }
        }
        auto c = mint<MOD>(1) / mint<MOD>(inverse ? n : 1);
        for (auto&& e : this->a) e *= c;
    }
    
    FPS convolution_naive(FPS &a, FPS &b) const {
        int n = int(a.size()), m = int(b.size());
        FPS ans(n+m-1);
        if (n < m) {
            for (int j = 0; j < m; j++) {
                for (int i = 0; i < n; i++) ans[i + j] += a[i]*b[j];
            }
        } 
        else {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) ans[i + j] += a[i]*b[j];
            }
        }
        return ans;
    }

    FPS& convolution_inplace(FPS b) {
        if (this->size() == 0 || b.size() == 0) {
            this->a.clear();
            return *this;
        }
        if (!any) {
            int n = this->size(), m = b.size(), sz = 1 << __lg(2*(n+m-1)-1);
            if (min(n, m) <= 60) return *this = convolution_naive(*this,b);
            this->resize(sz), this->ntt(false);
            b.resize(sz), b.ntt(false);
            for (int i = 0; i < sz; i++) this->a[i] *= b[i];
            this->ntt(true), this->resize(n + m - 1);
            return *this;
        }
        else {
            int n = this->a.size(), m = b.a.size();
            static constexpr int mod0 = 998244353, mod1 = 1300234241, mod2 = 1484783617;
            FormalPowerSeries< mod0 > l0(n), r0(m);
            FormalPowerSeries< mod1 > l1(n), r1(m);
            FormalPowerSeries< mod2 > l2(n), r2(m);
            for (int i = 0; i < n; i++) l0.a[i] = this->a[i].x, l1.a[i] = this->a[i].x, l2.a[i] = this->a[i].x;
            for (int j = 0; j < m; j++) r0.a[j] = b.a[j].x, r1.a[j] = b.a[j].x, r2.a[j] = b.a[j].x;
            l0 *= r0;
            l1 *= r1;
            l2 *= r2;
            crt(*this,l0,l1,l2);
            return *this;
        }
    }

    template<const int MOD0, const int MOD1, const int MOD2>
    static void crt(FPS &fps,
             const FormalPowerSeries<MOD0> &fps0, 
             const FormalPowerSeries<MOD1> &fps1, 
             const FormalPowerSeries<MOD2> &fps2) {
        assert(fps0.size() == fps1.size() && fps0.size() == fps2.size());
        int n = (int)fps0.size();
        fps.resize(n);
        static const mint<MOD1> im0 = mint<MOD1>(MOD0).inv();
        static const mint<MOD2> im1 = mint<MOD2>(MOD1).inv(), im0m1 = im1/MOD0;
        static const mint<MOD> m0 = MOD0, m0m1 = m0*MOD1;
        for (int i = 0; i < n; i++) {
            int y0 = fps0.a[i].x;
            int y1 = (im0*(fps1.a[i]-y0)).x;
            int y2 = (im0m1*(fps2.a[i]-y0)-im1*y1).x;
            fps.a[i] = m0m1*y2+y0+m0*y1;
        }
    }

    struct Fact {
    private:
        int N;
    public:
        vector< mint< MOD > > FACT, IFACT;
        Fact(int n) : N(n) {
            FACT.resize(n + 1);
            IFACT.resize(n + 1);
            FACT[0] = 1;
            for (int i = 1; i <= n; i++) {
                FACT[i] = FACT[i - 1] * i;
            }
            IFACT[n] = FACT[n].inv();
            for (int i = n-1; i >= 0; i--) {
                IFACT[i] = IFACT[i+1] * (i+1);
            }
        }
    };

    FPS rev() const {
        FPS ret(*this);
        reverse(ret.a.begin(), ret.a.end());
        return ret;
    }

    void shrink() {
        while (this->a.size() && this->a.back() == 0) this->a.pop_back();
    }

    static vector<FPS> subproduct_tree(const vector<mint<MOD>> &xs) {
        int n = (int) xs.size();
        int k = 1;
        while(k < n) k <<= 1;
        vector<FPS> g(2 * k, {1});
        for(int i = 0; i < n; i++) g[k + i] = {-xs[i], 1};
        for(int i = k; i-- > 1;) g[i] = g[i << 1] * g[i << 1 | 1];
        return g;
    }

    FPS _sqrt(int s) const {
		assert(this->a[0]==1);
		static const mint<MOD> half=mint<MOD>(1)/2;
		FPS f({1}),g({1}),z({1});
		for(int n=1;n<s;n*=2){
			for (int i = 0; i < n; i++) z[i]*=z[i];
			z.ntt(true);
            
			FPS delta(2*n),gbuf(2*n);
			for (int i = 0; i<n; i++) delta[n+i] = z[i] - (i<size()?this->a[i]:0) - (n+i<size()?this->a[n+i]:0);
            copy(g.a.begin(),g.a.end(), gbuf.a.begin());
			delta.ntt(false);
			gbuf.ntt(false);
			for (int i = 0;i < 2*n; i++) delta[i]*=gbuf[i];
			delta.ntt(true);

			f.resize(2*n);
            for(int i=n;i<2*n;i++) f[i]=-half*delta[i];
			
			if(2*n>=s)break;
			
			z=f;
			z.ntt(false);
			
			FPS eps=gbuf;
			for (int i = 0;i < 2*n;i++) eps[i]*=z[i];
			eps.ntt(true);
			
			for(int i = 0; i < n; i++)eps[i]=0;
			eps.ntt(false);
			
			for(int i = 0; i < 2*n; i++)eps[i]*=gbuf[i];
			eps.ntt(true);
			g.resize(2*n);
			for(int i = n; i < 2*n; i++)g[i]=-eps[i];
		}
		f.resize(s);
		return f;
	}

public:
    vector<mint<MOD>> a;

    FormalPowerSeries(int sz = 0) {
        this->a.resize(sz, 0);
    }

    FormalPowerSeries(const std::initializer_list<mint<MOD>> v) {
        this->a = v;
    }

    FormalPowerSeries(const std::vector<mint<MOD>> &v) {
        this->a = v;
    }

    int size() const {
        return a.size();
    }

    void resize(size_t sz, mint<MOD> m = mint<MOD>(0)) {
        this->a.resize(sz,m);
    }

    FPS operator+(const mint<MOD> &a) const { return FPS(*this) += a; }
    FPS operator+(const FPS &a) const { return FPS(*this) += a; }
    FPS operator-(const mint<MOD> &a) const { return FPS(*this) -= a; }
    FPS operator-(const FPS &a) const { return FPS(*this) -= a; }
    FPS operator*(const mint<MOD> &a) const { return FPS(*this) *= a; }
    FPS operator*(const long long a) const { return FPS(*this) *= a; }
    FPS operator*(const FPS &a) const { return FPS(*this) *= a; }
	FPS operator/(const mint<MOD> &a) const { return FPS(*this) /= a;}
    FPS operator/(const FPS &a) const { return FPS(*this) /= a; }
    FPS operator%(const FPS &a) const { return FPS(*this) %= a; }
    FPS &operator+=(const mint<MOD> &v) {
        this->a[0] += v;
        return *this;
    }
    FPS &operator+=(const FPS &r) {
        this->resize(max((int)this->size(),r.size()));
        for(int i = 0; i < (int)r.size(); i++) this->a[i] += r.a[i];
        return *this;
    }
    FPS &operator-=(const mint<MOD> &v) {
        this->a[0] -= v;
        return *this;
    }
    FPS &operator-=(const FPS &r) {
        this->resize(max((int)this->size(),r.size()));
        for(int i = 0; i < (int)r.size(); i++) this->a[i] -= r.a[i];
        return *this;
    }
    FPS &operator*=(const mint<MOD> &v) {
        for (int i = 0; i < this->size(); i++) this->a[i] *= v;
        return *this;
    }
    FPS &operator*=(const long long v) {
        for (int i = 0; i < this->size(); i++) this->a[i] *= v;
        return *this;
    }
    FPS &operator*=(const FPS &r) {
        this->convolution_inplace(r);
        return *this;
    }
	FPS &operator/=(const mint<MOD> &v){
		return *this *= v.inv();
	}
    FPS &operator/=(const FPS &r) {
        if (this->size() < r.size()) {
            this->a.clear();
            return *this;
        }
        int n = this->size() - r.size() + 1;
        if ((int)r.size() <= 64) {
            FPS f(*this), g(r);
            g.shrink();
            mint<MOD> coeff = g.a.back().inv();
            for (auto &x : g.a) x *= coeff;
            int deg = (int)f.size() - (int)g.size() + 1;
            int gs = g.size();
            FPS quo(deg);
            for (int i = deg - 1; i >= 0; i--) {
                quo[i] = f[i + gs - 1];
                for (int j = 0; j < gs; j++) f[i + j] -= quo[i] * g[j];
            }
            *this = quo * coeff;
            this->resize(n, 0);
            return *this;
        }
        return *this = ((*this).rev().low(n) * r.rev().inverse(n)).low(n).rev();
    }

    FPS &operator%=(const FPS &Q) {
        if(Q.size() > this->size()) return *this;
        if(Q.size() < 32) {
            int dQ = Q.size()-1;
            while(dQ && Q.a[dQ] == 0) dQ--;
            assert(Q.a[dQ] != 0);
            for(int i = this->size()-1; i >= dQ; i--){
                if(this->a[i] == 0) continue;
                mint<MOD> x = this->a[i] / Q.a[dQ];
                this->a[i] = 0;
                for(int j = 1; j <= dQ; j++){
                    this->a[i - j] -= x * Q.a[dQ - j];
                }
            }
            shrink();
            return *this;
        }
        FPS P = (*this) / Q;
        P *= Q;
        int dR = -1;
        for(int i = 0; i < Q.size()-1; i++){
            P.a[i] = this->a[i] - P.a[i];
            if(P.a[i] != 0) dR = i;
        }
        this->a.resize(dR + 1);
        for(int i = 0; i <= dR; i++) this->a[i] = P.a[i];
        return *this;
    }


    FPS low(int s) const {
        return FPS(vector<mint<MOD>>(this->a.begin(),this->a.begin()+min(max(s,1),this->size())));
    }

    FPS inverse(int deg = -1) const {
        int n = this->size();
        assert(n != 0 && this->a[0].x != 0);
        if(deg == -1) deg = n;

        if (!any) {
            FPS r({this->a[0].inv()});
            for(int m=1;m<deg;m*=2) {
                FPS f(vector<mint<MOD>>(this->a.begin(), this->a.begin() + min(n, 2*m)));
                FPS g(r);
                f.resize(2*m), f.ntt(false);
                g.resize(2*m), g.ntt(false);
                for (int i = 0; i < 2*m; i++) f[i] *= g[i];
                f.ntt(true);
                f.a.erase(f.a.begin(), f.a.begin() + m);
                f.resize(2*m), f.ntt(false);
                for (int i = 0; i < 2*m; i++) f[i] *= g[i];
                f.ntt(true); 
                for (int i = 0; i < 2*m; i++) f[i] = -f[i];
                r.a.insert(r.a.end(), f.a.begin(), f.a.begin() + m);
            }
            return r.low(deg);
        }
        else {

            FPS r({this->a[0].inv()});
            for (int i = 1; i < deg; i <<= 1)
                r = (r*2 - r.square()*(*this).low(i<<1)).low(i<<1);
            return r.low(deg);
        }
    }

    FPS& square_inplace() {
        if (this->size() == 0) {
            return *this;
        }
        if (!any) {
            int n = this->size(), sz = 1 << __lg(2*(n+n-1)-1);
            if (n <= 60) return *this = convolution_naive(*this,*this);
            this->resize(sz), this->ntt(false);
            for (int i = 0; i < sz; i++) this->a[i] *= this->a[i];
            this->ntt(true), this->resize(n+n-1);
            return *this;
        }
        else {
            int n = this->a.size();
            static constexpr int mod0 = 998244353, mod1 = 1300234241, mod2 = 1484783617;
            FormalPowerSeries< mod0 > f0(n);
            FormalPowerSeries< mod1 > f1(n);
            FormalPowerSeries< mod2 > f2(n);
            for (int i = 0; i < n; i++) f0.a[i] = this->a[i].x, f1.a[i] = this->a[i].x, f2.a[i] = this->a[i].x;
            f0.square_inplace();
            f1.square_inplace();
            f2.square_inplace();
            crt(*this,f0,f1,f2);
            return *this;
        }
    }
    FPS square() const { return FPS(*this).square_inplace(); }

    FPS& differential_inplace() {
        const int n = (int)this->a.size();
        assert(n > 0);
        for(int i = 1; i < n; i++) this->a[i-1] = this->a[i] * i;
        this->a[n-1] = 0;
        return *this;
    }
    FPS differential() const { return FPS(*this).differential_inplace(); }

    FPS& integral_inplace() {
        const int n = (int)this->a.size();
        assert(n > 0);
        this->a.insert(this->a.begin(),0);
        vector<mint<MOD>> inv(n+1); inv[1] = 1;
        for (int i = 2; i <= n; i++) inv[i] = -inv[MOD%i]*(MOD/i);
        for (int i = 2; i <= n; i++) this->a[i] *= inv[i];
        return *this;
    }
    FPS integral() const { return FPS(*this).integ_inplace(); }

    FPS& log_inplace(int deg = -1) {
        int n = this->size();
        assert(n > 0 && this->a[0] == 1);
        if (deg == -1) deg = n;
        if (deg < n) this->resize(deg);
        FPS f_inv = this->inverse();
        this->differential_inplace();
        *this *= f_inv;
        this->resize(deg);
        this->integral_inplace();
        return *this;
    }  
    FPS log(const int deg = -1) const { return FPS(*this).log_inplace(deg); }

    FPS& exp_inplace(int deg = -1) {
        if (!any) {
            int n = this->size();
            assert(n > 0 && (*this)[0] == 0);
            if (deg == -1) deg = n;
            assert(deg >= 0);
            FPS g({1}), g_fft;
            this->resize(deg);
            this->a[0] = 1;
            FPS h_drv = this->differential();
            for (int m = 1; m < deg; m *= 2) {
                FPS f_fft(vector<mint<MOD>>(this->a.begin(), this->a.begin() + m));
                f_fft.resize(2*m), f_fft.ntt(false);
                mint<MOD> invm = m; invm = invm.inv();

                if (m > 1) {
                    FPS _f(m);
                    for(int i = 0; i < m; i++) _f[i] = f_fft[i] * g_fft[i];
                    _f.ntt(true);
                    _f.a.erase(_f.a.begin(), _f.a.begin() + m/2);
                    _f.resize(m), _f.ntt(false);
                    for(int i = 0; i < m; i++) _f[i] *= g_fft[i];
                    _f.ntt(true);
                    _f.resize(m/2);
                    for (int i = 0; i < m/2; i++) _f[i] = -_f[i];
                    g.a.insert(g.a.end(), _f.a.begin(), _f.a.begin() + m/2);
                }

                FPS t(vector<mint<MOD>>(this->a.begin(), this->a.begin() + m)); 
                t.differential_inplace();
                {
                    FPS r(vector<mint<MOD>>(h_drv.a.begin(), h_drv.a.begin() + m-1));
                    r.resize(m); r.ntt(false);
                    for (int i = 0; i < m; i++) r.a[i] *= f_fft.a[i];
                    r.ntt(true);
                    t -= r;
                    t.a.insert(t.a.begin(), t.a.back()); t.a.pop_back();
                }

                t.resize(2*m); t.ntt(false); 
                g_fft = g; g_fft.resize(2*m); g_fft.ntt(false);
                for (int i = 0; i < 2*m; i++) t.a[i] *= g_fft.a[i];
                t.ntt(true);
                t.resize(m);
                
                FPS v(vector<mint<MOD>>(this->a.begin() + m, this->a.begin() + min(deg, 2*m))); v.resize(m);
                t.a.insert(t.a.begin(), m-1, 0); t.a.push_back(0);
                t.integral_inplace();
                for (int i = 0; i < m; i++) v.a[i] -= t.a[m+i];

                v.resize(2*m); v.ntt(false);
                for (int i = 0; i < 2*m; i++) v.a[i] *= f_fft.a[i];
                v.ntt(true);
                v.resize(m);

                for (int i = 0; i < min(deg-m,m); i++) this->a[m+i] = v.a[i];
            }
            return *this;
        }
        else {
            assert(this->size() == 0 || this->a[0] == 0);
            if (deg == -1) deg = (int)this->size();
            FPS r({1});
            for (int i = 1; i < deg; i <<= 1) {
                r = (r*(this->low(i << 1)+mint<MOD>(1)-r.log(i << 1))).low(i << 1);
            }
            return *this = r.low(deg);
        }
    }
    FPS exp(const int deg = -1) const { return FPS(*this).exp_inplace(deg); }

    FPS& pow_inplace(ll k, int deg = -1) {
        int n = this->size();
        if (deg == -1) deg = n;
        assert(deg >= 0);
        int l = 0;
        while (this->a[l] == 0) ++l;
        if (l > deg/k) return *this = FPS(deg);
        mint<MOD> ic = this->a[l].inv();
        mint<MOD> pc = this->a[l].pow(k);
        this->a.erase(this->a.begin(), this->a.begin() + l);
        *this *= ic.x;
        this->log_inplace();
        *this *= k;
        this->exp_inplace();
        *this *= pc.x;
        this->a.insert(this->a.begin(), l*k, 0);
        this->resize(deg);
        return *this;
    }
    FPS pow(const ll k, const int deg = -1) const { return FPS(*this).pow_inplace(k, deg); }

    FPS& sqrt_inplace(int deg = -1) {
        if (deg == -1) deg = this->size();
        int n = this->size(), z = 0;
        for(;z<n&&this->a[z]==0;z++);
        if(z==n) {this->resize(deg); return *this;}
        if(z%2) return *this = {};
        mint<MOD> w = this->a[z].sqrt();
        if(w*w!=this->a[z]) return *this = {};
        int s=deg-z/2;
        mint<MOD> az = this->a[z];
        this->a.erase(this->a.begin(),this->a.begin()+z);
        *this /= az;
        if (!any) *this = this->_sqrt(s);
        else {
            FPS g({1});
            mint<MOD> two_inv = mint<MOD>(2).inv();
            for (int i = 1; i < s; i*=2) {
                g.resize(i*2);
                g += (*this).low(i*2)*g.inverse();
                g *= two_inv;
            }
            *this = g.low(s);
        }
        *this *= w;
        this->a.insert(this->a.begin(),z/2,0);
        return *this;
    }
    FPS sqrt(int deg = -1) const { return FPS(*this).sqrt_inplace(deg); }

    FPS& shift_inplace(const mint<MOD> &c) {
        int n = this->size();
        Fact fc(n);
        for (int i = 0; i < n; i++) this->a[i] *= fc.FACT[i];
        reverse(this->a.begin(), this->a.end());
        FPS g(n);
        mint<MOD> cp = 1; 
        for (int i = 0; i < n; i++) g[i] = cp * fc.IFACT[i], cp *= c;
        this->convolution_inplace(g);
        this->a.resize(n);
        reverse(this->a.begin(), this->a.end());
        for (int i = 0; i < n; i++) this->a[i] *= fc.IFACT[i];
        return *this;
    }
    FPS shift(const mint<MOD> &c) const { return FPS(*this).shift_inplace(c); }

    vector<mint<MOD>> multipoint_evaluation(const vector<mint<MOD>> &xs) {
        auto g = subproduct_tree(xs);
        int m = (int) xs.size(), k = (int) g.size() / 2;
        g[1] = (*this) % g[1];
        for(int i = 2; i < k + m; i++) g[i] = g[i >> 1] % g[i];
        vector<mint<MOD>> ys(m);
        for(int i = 0; i < m; i++) {
            ys[i] = (g[k + i].size() == 0 ? mint<MOD>(0) : g[k + i][0]);
        }
        return ys;
    }
    vector<mint<MOD>> multipoint_evaluation(const FPS &xs) {
        return multipoint_evaluation(xs.a);
    }

    mint<MOD> &operator[](int x) {
        assert(0 <= x && x < (int)this->a.size());
        return a[x];
    }
    
    friend std::ostream &operator<<(std::ostream &os, const FPS &p) {
        os << "[ ";
        for (int i = 0; i < p.size(); ++i) {
            os << p.a[i] << " ";
        }
        os << "]";
        return os;
    }
};

int k;

void dfs(int v, int p, vector<vector<int>> &g, vector<FormalPowerSeries<MOD>> &dp, vector<int> &a) {
    dp[v].resize(a[v]+1);
    dp[v][a[v]] += 1;
    dp[v].resize(min(k,a[v])+1);
    for (int u : g[v]) {
        if (u == p) continue;
        dfs(u,v,g,dp,a);
        dp[u][0] += 1;
        dp[v] *= dp[u];
        dp[v].resize(k+1);
    }
}

int main() {
    int n;cin >> n >> k;
    vector<int> a(n);
    vector<vector<int>> g(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n-1; i++) {
        int p;cin >> p;
        g[i+1].push_back(p-1);
        g[p-1].push_back(i+1);
    }
    vector<FormalPowerSeries<MOD>> dp(n,{0});
    dfs(0,-1,g,dp,a);
    if (dp[0].size() < k+1) puts("0");
    else cout << dp[0][k] << endl;
    return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 21392
final_rank: 9