#if __INCLUDE_LEVEL__ == 0 #include __FILE__ namespace r7h { using fp = atcoder::modint998244353; void main(int) { int n; scan(n); vector p(n, -1); vector> g(n); for (int v : rep(1, n)) { scan(p[v]); --p[v]; g[p[v]] += v; } fp ans = 1; vector d(n); for (int v : rep(n)) { for (int u : g[v]) { d[u] = d[v] + 1; } if (v) { ans *= d[p[v]] + 1; } } println(ans.val()); } } // namespace r7h #else #define MULTI_CASES 0 #define INTERACTIVE 0 #ifndef LOCAL #define LOCAL 0 #endif #if !LOCAL #define NDEBUG #endif #ifndef __GLIBCXX_TYPE_INT_N_0 #define __GLIBCXX_TYPE_INT_N_0 __int128 #endif #include #include #include namespace r7h { using namespace std; void main(int); } // namespace r7h #if LOCAL #include #else #define DUMP(...) void(0) #endif #define LIFT(FN) \ [](Ts_&&... xs_) -> decltype(auto) { return FN(static_cast(xs_)...); } #define LAMBDA(...) \ [&]([[maybe_unused]] T1_&& _1 = nullptr, [[maybe_unused]] T2_&& _2 = nullptr) \ -> decltype(auto) { \ return __VA_ARGS__; \ } namespace r7h { template class fix : F { public: explicit fix(F f) : F(move(f)) {} template decltype(auto) operator()(Ts&&... xs) const { return F::operator()(ref(*this), forward(xs)...); } }; template decay_t decay_copy(T&& x) { return forward(x); } template auto ref_or_move(remove_reference_t& x) { if constexpr (is_reference_v && !is_placeholder_v>) { return ref(x); } else { return move(x); } } template > bool const is_lambda_expr = is_placeholder_v || is_bind_expression_v; #define UNARY_LAMBDA(OP) \ template >* = nullptr> \ auto operator OP(T&& x) { \ return bind([](T_&& x_) -> decltype(auto) { return OP forward(x_); }, ref_or_move(x)); \ } #define BINARY_LAMBDA(OP) \ template || is_lambda_expr>* = nullptr> \ auto operator OP(T1&& x, T2&& y) { \ auto f = [](T1_&& x_, T2_&& y_) -> decltype(auto) { \ return forward(x_) OP forward(y_); \ }; \ return bind(move(f), ref_or_move(x), ref_or_move(y)); \ } BINARY_LAMBDA(+=) BINARY_LAMBDA(-=) BINARY_LAMBDA(*=) BINARY_LAMBDA(/=) BINARY_LAMBDA(%=) BINARY_LAMBDA(&=) BINARY_LAMBDA(|=) BINARY_LAMBDA(^=) BINARY_LAMBDA(<<=) BINARY_LAMBDA(>>=) UNARY_LAMBDA(++) UNARY_LAMBDA(--) UNARY_LAMBDA(+) UNARY_LAMBDA(-) BINARY_LAMBDA(+) BINARY_LAMBDA(-) BINARY_LAMBDA(*) BINARY_LAMBDA(/) BINARY_LAMBDA(%) UNARY_LAMBDA(~) BINARY_LAMBDA(&) BINARY_LAMBDA(|) BINARY_LAMBDA(^) BINARY_LAMBDA(<<) BINARY_LAMBDA(>>) BINARY_LAMBDA(==) BINARY_LAMBDA(!=) BINARY_LAMBDA(<) BINARY_LAMBDA(>) BINARY_LAMBDA(<=) BINARY_LAMBDA(>=) UNARY_LAMBDA(!) BINARY_LAMBDA(&&) BINARY_LAMBDA(||) #undef UNARY_LAMBDA #undef BINARY_LAMBDA using namespace placeholders; using i8 = signed char; using u8 = unsigned char; using i16 = short; using u16 = unsigned short; using i32 = int; using u32 = unsigned; using i64 = long long; using u64 = unsigned long long; using i128 = __int128; using u128 = unsigned __int128; template struct signed_int; template struct unsigned_int; #define INT_TYPE(N) \ template <> struct signed_int { using type = i##N; }; \ template <> struct unsigned_int { using type = u##N; }; INT_TYPE(8) INT_TYPE(16) INT_TYPE(32) INT_TYPE(64) INT_TYPE(128) #undef INT_TYPE template using signed_int_t = typename signed_int::type; template using unsigned_int_t = typename unsigned_int::type; namespace scan_impl { #if INTERACTIVE || LOCAL bool scan(char& c) { return scanf(" %c", &c) != EOF; } bool scan(string& s) { char c; if (!scan(c)) { return false; } for (s = c;; s += c) { c = char(getchar()); if (c <= ' ') { ungetc(c, stdin); break; } } return true; } template enable_if_t, bool> scan(T& x) { char c; if (!scan(c)) { return false; } make_unsigned_t u = (c == '-' ? getchar() : c) & 15; while (true) { if (int t = getchar(); '0' <= t && t <= '9') { (u *= 10) += t & 15; } else { ungetc(t, stdin); break; } } x = T(c == '-' ? -u : u); return true; } template enable_if_t, bool> scan(T& x) { return scanf(is_same_v ? "%f" : is_same_v ? "%lf" : "%Lf", &x) != EOF; } #else char buf[1 << 15]; char* ptr = buf; char* last = buf; bool scan(char& c) { for (;; ++ptr) { if (last - ptr < 64) { last = move(ptr, last, buf); ptr = buf; last += read(STDIN_FILENO, last, end(buf) - last - 1); *last = '\0'; } if (ptr == last) { return false; } if (' ' < *ptr) { c = *ptr++; return true; } } } bool scan(string& s) { char c; if (!scan(c)) { return false; } for (s = c; ' ' < *ptr; s += c) { scan(c); } return true; } template enable_if_t, bool> scan(T& x) { char c; if (!scan(c)) { return false; } make_unsigned_t u = (c == '-' ? *ptr++ : c) & 15; while ('0' <= *ptr && *ptr <= '9') { (u *= 10) += *ptr++ & 15; } x = T(c == '-' ? -u : u); return true; } template enable_if_t, bool> scan(T& x) { char c; if (!scan(c)) { return false; } int n; sscanf(--ptr, is_same_v ? "%f%n" : is_same_v ? "%lf%n" : "%Lf%n", &x, &n); ptr += n; return true; } #endif template auto scan(R&& r) -> decltype(begin(r), end(r), true) { return all_of(begin(r), end(r), LIFT(scan)); } template enable_if_t scan(Ts&&... xs) { return (... && scan(forward(xs))); } } // namespace scan_impl using scan_impl::scan; namespace print_impl { #if INTERACTIVE || LOCAL template void print(char c) { if (c) { putchar(c); } if (c == '\n') { fflush(stdout); } } template enable_if_t> print(T x) { char buf[64]; char* ptr = to_chars(buf, end(buf), +x).ptr; for_each(buf, ptr, LIFT(print)); } template enable_if_t> print(T x) { printf(is_same_v ? "%.6f" : is_same_v ? "%.15f" : "%.18Lf", x); } #else char buf[1 << 15]; char* ptr = buf; __attribute__((destructor)) void flush() { if (write(STDOUT_FILENO, buf, ptr - buf) == -1) { abort(); } ptr = buf; } template void print(char c) { if (end(buf) - ptr < 64) { flush(); } if (c) { *ptr++ = c; } } template enable_if_t> print(T x) { print('\0'); ptr = to_chars(ptr, end(buf), +x).ptr; } template enable_if_t> print(T x) { print('\0'); ptr += snprintf(ptr, end(buf) - ptr, is_same_v ? "%.6f" : is_same_v ? "%.15f" : "%.18Lf", x); } #endif template void print(char const*); template auto print(R&& r) -> void_t { [[maybe_unused]] char c = '\0'; for (auto&& e : r) { if constexpr (!is_same_v, char>) { print(exchange(c, Sep)); } print(e); } } template void print(char const* s) { print(string_view(s)); } template enable_if_t print(Ts&&... xs) { [[maybe_unused]] char c = '\0'; (..., (print(exchange(c, Sep)), print(forward(xs)))); } } // namespace print_impl using print_impl::print; template void println(Ts&&... xs) { print(forward(xs)...); print(End); } template auto operator++(T& x, int) -> decltype(++x, T(x)) { T ret = x; ++x; return ret; } template auto operator--(T& x, int) -> decltype(--x, T(x)) { T ret = x; --x; return ret; } #define BINARY_ARITH_OP(OP) \ template > \ auto operator OP(T1 const& x, T2 const& y) -> decltype(declval() OP##= y, T(x)) { \ T ret = T(x); \ ret OP##= y; \ return ret; \ } BINARY_ARITH_OP(+) BINARY_ARITH_OP(-) BINARY_ARITH_OP(*) BINARY_ARITH_OP(/) BINARY_ARITH_OP(%) BINARY_ARITH_OP(&) BINARY_ARITH_OP(|) BINARY_ARITH_OP(^) BINARY_ARITH_OP(<<) BINARY_ARITH_OP(>>) #undef BINARY_ARITH_OP #define COMPARISON_OP(OP, E) \ template \ auto operator OP(T1 const& x, T2 const& y) -> decltype(E) { \ return E; \ } COMPARISON_OP(!=, !(x == y)) COMPARISON_OP(>, y < x) COMPARISON_OP(<=, !(y < x)) COMPARISON_OP(>=, !(x < y)) #undef COMPARISON_OP template class iter_base { D& derived() { return static_cast(*this); } D const& derived() const { return static_cast(*this); } public: using iterator_category = C; using value_type = decay_t; using difference_type = int; using pointer = void; using reference = R; #define REQUIRE(CAT) template >* = nullptr> R operator*() const { return derived().deref(); } REQUIRE(random_access) R operator[](int n) const { return *(derived() + n); } D& operator++() & { derived().inc(); return derived(); } REQUIRE(bidirectional) D& operator--() & { derived().dec(); return derived(); } REQUIRE(random_access) D& operator+=(int n) & { derived().adv(n); return derived(); } REQUIRE(random_access) D& operator-=(int n) & { derived().adv(-n); return derived(); } REQUIRE(random_access) friend D operator+(D const& x, int n) { D ret = x; ret += n; return ret; } REQUIRE(random_access) friend D operator+(int n, D const& x) { return x + n; } REQUIRE(random_access) friend D operator-(D const& x, int n) { D ret = x; ret -= n; return ret; } REQUIRE(random_access) friend int operator-(D const& x, D const& y) { return y.dist_to(x); } friend bool operator==(D const& x, D const& y) { return x.eq(y); } REQUIRE(random_access) friend bool operator<(D const& x, D const& y) { return x - y < 0; } #undef REQUIRE }; struct int_iter : iter_base { int v; int_iter() = default; int_iter(int v) : v(v) {} int deref() const { return v; } bool eq(int_iter const& x) const { return v == x.v; } void inc() { ++v; } void dec() { --v; } void adv(int n) { v += n; } int dist_to(int_iter const& x) const { return x.v - v; } }; template class range { I b, e; public: explicit range(I first, I last) : b(move(first)), e(move(last)) {} I begin() const { return b; } I end() const { return e; } }; auto rep(int l, int r) { return range(min(l, r), r); } auto rep(int n) { return rep(0, n); } auto rep1(int l, int r) { return rep(l, r + 1); } auto rep1(int n) { return rep(1, n + 1); } template auto rev(R&& r) { return range(make_reverse_iterator(end(r)), make_reverse_iterator(begin(r))); } template auto sz(R&& r) -> decltype(int(size(forward(r)))) { return int(size(forward(r))); } template T power1(T x, N n, Op op) { assert(1 <= n); for (; ~n & 1; n >>= 1) { x = op(x, x); } T ret = x; while (n >>= 1) { x = op(x, x); if (n & 1) { ret = op(move(ret), x); } } return ret; } template T power(T x, N n) { if (n == 0) { return T{1}; } if (n < 0) { return T{1} / power1(move(x), -n, multiplies{}); } return power1(move(x), n, multiplies{}); } template T div_floor(T x, T y) { return T(x / y - ((x ^ y) < 0 && x % y)); } template T div_ceil(T x, T y) { return T(x / y + (0 <= (x ^ y) && x % y)); } template bool chmin(T& x, U&& y) { return y < x ? x = forward(y), true : false; } template bool chmax(T& x, U&& y) { return x < y ? x = forward(y), true : false; } template T const inf_v = numeric_limits::max() / 2; int const inf = inf_v; mt19937_64 mt(_rdtsc()); template T rand(T a, T b) { if constexpr (is_integral_v) { return uniform_int_distribution(a, b)(mt); } else { return uniform_real_distribution(a, b)(mt); } } } // namespace r7h int main() { int t = 1; if (MULTI_CASES) { r7h::scan(t); } for (int i : r7h::rep(t)) { r7h::main(i); } assert(!r7h::scan(t)); } #define all(c) begin(c), end(c) #include #endif