Problem:
G: Tree
問題
N
頂点からなる木が与えられます。木の各頂点には
1
から
N
の番号が割り振られています。また、
N−1
本の辺のうち、
i\ (= 1, 2, ..., N-1)
本目の辺は頂点
u_i
と頂点
v_i
とを結んでいます。
この木の
K
個の空でない部分グラフの組であって、各部分グラフがいずれも連結で、どの二つの相異なる部分グラフも頂点を共有しないものの個数を求めるプログラムを作成してください。ただし答えがとても大きくなることがあるため、
998244353
で割ったあまりを答えてください。
なお、
K
個の部分グラフからなる集合が同一のものは、
K
個の部分グラフの順序が異なるものも同一視するものとします。
入力形式
N
K
u_1
v_1
:
u_{N-1}
v_{N-1}
制約
2 \leq N \leq 10^{5}
1 \leq K \leq min ( N, 300 )
1 \leq u_i, v_i \leq N
u_i \neq v_i
i \neq j
に対して
(u_i, v_i) \neq (u_j, v_j)
入力はすべて整数で与えられる。
与えられるグラフは木であることが保証される。
出力形式
答えを表す整数を一行に出力してください。
998244353
で割ったあまりを出力することに注意してください。
入力例 1
3 2
1 2
1 3
出力例 1
5
以下の
5
通りがあります:
\{ 1 \}
と
\{ 2 \}
\{ 1 \}
と
\{ 3 \}
\{ 2 \}
と
\{ 3 \}
\{ 1, 2 \}
と
\{ 3 \}
\{ 1, 3 \}
と
\{ 2 \}
入力例 2
4 4
1 2
1 3
1 4
出力例 2
1
( \{ 1 \}, \{ 2 \}, \{ 3 \}, \{ 4 \} )
の
1
通りしかありません。
入力例 3
7 4
1 7
2 1
7 4
3 4
5 7
6 3
出力例 3
166

Submitted solutions:

code_snippet: // AOJ #2958 Tree
// 2025.4.21

#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353, G = 3;

#define gc() getchar_unlocked()

int Cin() {
	int n = 0; int c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

inline int add(int a,int b){ a+=b; return a>=MOD? a-MOD : a; }
inline int sub(int a,int b){ a-=b; return a<0? a+MOD : a; }
inline int mul(long long a,long long b){ return int(a*b%MOD); }
int modexp(int a,int e=MOD-2){
    int r=1;
    while(e){
        if(e&1) r=mul(r,a);
        a=mul(a,a);
        e>>=1;
    }
    return r;
}

int NTT_n;
vector<int> rev;
inline int bitlen(int x){ return 31-__builtin_clz(x); }
void init_ntt(int K){
    NTT_n = 1;
    while(NTT_n < (K+1)*2-1) NTT_n <<= 1;
    int L = bitlen(NTT_n);
    rev.assign(NTT_n, 0);
    for(int i=1; i<NTT_n; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(L-1));
}

void ntt(vector<int>& a, bool inv){
    int n = NTT_n;
    for(int i=0; i<n; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
    for(int len=2; len<=n; len<<=1){
        int wlen = modexp(G, (MOD-1)/len);
        if(inv) wlen = modexp(wlen);
        for(int i=0; i<n; i+=len){
            int w = 1;
            for(int j=0; j<len/2; j++){
                int u = a[i+j];
                int v = mul(a[i+j+len/2], w);
                a[i+j]   = add(u, v);
                a[i+j+len/2] = sub(u, v);
                w = mul(w, wlen);
            }
        }
    }
    if(inv){
        int invn = modexp(n);
        for(int &x: a) x = mul(x, invn);
    }
}

const int NAIVE_LIMIT = 4096;
vector<int> convTrunc(const vector<int>& A, const vector<int>& B, int K){
    int as = A.size(), bs = B.size();
    int need = min(as + bs - 1, K+1);
    if((long long)as * bs <= NAIVE_LIMIT){
        vector<int> C(need, 0);
        for(int i=0; i<as; i++){
            if(!A[i]) continue;
            for(int j=0; j<bs && i+j<need; j++) C[i+j] = add(C[i+j], mul(A[i], B[j]));
        }
        return C;
    }
    static vector<int> fa, fb;
    fa.assign(NTT_n, 0);
    fb.assign(NTT_n, 0);
    for(int i=0; i<as; i++) fa[i] = A[i];
    for(int i=0; i<bs; i++) fb[i] = B[i];
    ntt(fa, false);
    ntt(fb, false);
    for(int i=0; i<NTT_n; i++) fa[i] = mul(fa[i], fb[i]);
    ntt(fa, true);
    fa.resize(need);
    return fa;
}

int N, K;
vector<vector<int>> ch;
vector<vector<int>> A, B, C;

void dfs(int u){
    for(int v: ch[u]) dfs(v);

    vector<int> f0(1,1), f1(1,1);
    for(int v: ch[u]){
        int sz0 = min(K+1, max((int)A[v].size(), (int)C[v].size()));
        vector<int> p0(sz0,0);
        for(int j=0; j<sz0; j++){
            int av = j<(int)A[v].size()?A[v][j]:0;
            int cv = j<(int)C[v].size()?C[v][j]:0;
            p0[j] = add(av, cv);
        }
        f0 = convTrunc(f0, p0, K);

        int sz1 = min(K+1, max({(int)A[v].size(), (int)B[v].size(), (int)C[v].size()}));
        vector<int> p1(sz1,0);
        for(int j=0; j<sz1; j++){
            int av = j<(int)A[v].size()?A[v][j]:0;
            int bv = j<(int)B[v].size()?B[v][j]:0;
            int cv = j<(int)C[v].size()?C[v][j]:0;
            p1[j] = add(add(av, bv), cv);
        }
        f1 = convTrunc(f1, p1, K);
    }

    A[u] = f0;
    B[u] = f1;
    C[u].assign(min(K+1, (int)B[u].size()+1), 0);
    for(int j=0; j<(int)B[u].size() && j+1<=K; j++) C[u][j+1] = B[u][j];
    while(A[u].size()>1 && A[u].back()==0) A[u].pop_back();
    while(B[u].size()>1 && B[u].back()==0) B[u].pop_back();
    while(C[u].size()>1 && C[u].back()==0) C[u].pop_back();
}

int main(){
    N = Cin(), K = Cin();
    init_ntt(K);

    vector<vector<int>> adj(N+1);
    for(int i=1;i<N;i++){
        int u = Cin(), v = Cin();
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    ch.assign(N+1, {});
    vector<int> stk{1}, par(N+1,0);
    par[1] = -1;
    while(!stk.empty()){
        int u = stk.back(); stk.pop_back();
        for(int v: adj[u]){
            if(v==par[u]) continue;
            par[v]=u;
            ch[u].push_back(v);
            stk.push_back(v);
        }
    }

    A.assign(N+1, {});
    B.assign(N+1, {});
    C.assign(N+1, {});
    dfs(1);

    int ans = 0;
    if(K < (int)A[1].size()) ans = add(ans, A[1][K]);
    if(K < (int)C[1].size()) ans = add(ans, C[1][K]);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 500
memory_kb: 396232
final_rank: 6

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define rep(i, m, n) for (ll i = (ll)m; i < (ll)n; i++)
#define drep(i, m, n) for (ll i = m - 1; i >= n; i--)
#define Endl endl
#define all(a) a.begin(), a.end()
#define pr(i, j) make_pair(i, j)
#define isin(x, l, r) (l <= x && x < r)
#define chmin(a, b) a = min(a, b)
#define chmax(a, b) a = max(a, b)
#define srt(ar) sort(ar.begin(), ar.end())
#define rev(ar) reverse(ar.begin(), ar.end())
#define jge(f, s, t) cout << (f ? s : t) << endl
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#define printar(ar)             \
    do                          \
    {                           \
        for (auto dbg : ar)     \
        {                       \
            cout << dbg << " "; \
        }                       \
        cout << endl;           \
    } while (0)
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
template <class T, ll n, ll idx = 0>
auto make_vec(const ll (&d)[n], const T &init) noexcept
{
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, ll n>
auto make_vec(const ll (&d)[n]) noexcept
{
    return make_vec(d, T{});
}
//////////////// 以下を貼る ////////////////
template <class T>
size_t HashCombine(const size_t seed, const T &v)
{
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
/* pair用 */
template <class T, class S>
struct std::hash<std::pair<T, S>>
{
    size_t operator()(const std::pair<T, S> &keyval) const noexcept
    {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
////////////////////////////////////////////

ll mod = 998244353;
ll n, K;
vector<vector<ll>> a;
vector<vector<ll>> b;
vector<vector<ll>> g;
void f(ll now, ll from)
{
    vector<ll> A(2), B(2);
    A[0] = 1;
    B[0] = 1;
    rep(i, 0, g[now].size())
    {
        ll nxt = g[now][i];
        if (nxt == from)
        {
            continue;
        }
        f(nxt, now);
        vector<ll> c(a[nxt].size());
        vector<ll> d(a[nxt].size());
        rep(j, 0, a[nxt].size())
        {
            c[j] = a[nxt][j] + b[nxt][j];
            d[j] = c[j];
            if (j != a[nxt].size() - 1)
            {
                d[j] += a[nxt][j + 1];
            }
        }
        vector<ll> S, T;
        rep(j, 0, B.size())
        {
            rep(k, 0, c.size())
            {
                if (j + k >= S.size())
                {
                    S.resize(j + k + 1);
                }
                S[j + k] += B[j] * c[k];
                S[j + k] %= mod;
            }
        }
        rep(j, 0, A.size())
        {
            rep(k, 0, d.size())
            {
                if (j + k >= T.size())
                {
                    T.resize(j + k + 1);
                }
                T[j + k] += A[j] * d[k];
                T[j + k] %= mod;
            }
        }
        A = T;
        B = S;
        if (A.size() > K + 1)
        {
            A.resize(K + 1);
        }
        if (B.size() > K + 1)
        {
            B.resize(K + 1);
        }
    }
    drep(i, A.size(), 1)
    {
        A[i] = A[i - 1];
    }
    A[0] = 0;
    a[now] = A;
    b[now] = B;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> K;
    g.resize(n);
    rep(i, 0, n - 1)
    {
        ll u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    a.resize(n);
    b.resize(n);
    f(0, -1);
    /*
    rep(i, 0, n)
    {
        printar(a[i]);
    }
    cout << endl;
    rep(i, 0, n)
    {
        printar(b[i]);
    }
    */
    ll ans = a[0][K] + b[0][K];
    ans %= 998244353;
    cout << ans << endl;
}
accuracy: 1
time_ms: 570
memory_kb: 511880
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int INF = (int)1e9 + 1001010;
constexpr ll llINF = (ll)4e18 + 22000020;
const string endn = "\n";
template <class T> inline vector<vector<T>> vector2(size_t i, size_t j, const T &init = T()) {return vector<vector<T>>(i, vector<T>(j, init));}
const string ELEM_SEPARATION = " ", VEC_SEPARATION = endn;
template<class T> istream& operator >>(istream &i, vector<T> &A) {for(auto &I : A) {i >> I;} return i;}
template<class T> ostream& operator <<(ostream &o, const vector<vector<T>> &A) {int i=A.size(); for(auto &I : A){o << I << (--i ? VEC_SEPARATION : "");} return o;}
template<class T> ostream& operator <<(ostream &o, const vector<T> &A) {int i=A.size(); for(auto &I : A){o << I << (--i ? ELEM_SEPARATION : "");} return o;}
template<class T> vector<T>& operator ++(vector<T> &A, int n) {for(auto &I : A) {I++;} return A;}
template<class T> vector<T>& operator --(vector<T> &A, int n) {for(auto &I : A) {I--;} return A;}
template<class T, class U> bool chmax(T &a, const U &b) {return ((a < b) ? (a = b, true) : false);}
template<class T, class U> bool chmin(T &a, const U &b) {return ((a > b) ? (a = b, true) : false);}
ll floor(ll a, ll b) {assert(b != 0); return((a%b != 0 && ((a>0) != (b>0))) ? a/b-1 : a/b);}
ll ceil (ll a, ll b) {assert(b != 0); return((a%b != 0 && ((a>0) == (b>0))) ? a/b+1 : a/b);}
// ================================== ここまでテンプレ ==================================
// type_traits, math
namespace atcoder {
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;
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
        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;
    for (long long a : {2, 7, 61}) {
        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;  // |m1 * u| <= |m1| * s <= b
        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}


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_signed_int = typename std::conditional<(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;
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>;
}  // namespace internal
}  // namespace atcoder

// modint
namespace atcoder {
template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint {
    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 = internal::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; }

    friend istream &operator >> (istream &i, mint &a) {long long v; i >> v; a = v; return i;}
    friend ostream &operator << (ostream &os, const mint &a) { return os << a.val(); }
  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
}  // namespace atcoder

using namespace atcoder;
using mint = modint998244353;

template<int m> istream & operator >> (istream &i, static_modint<m, (void*)nullptr> &a) { ll v; i >> v; a = v; return i; }
template<int m> ostream & operator << (ostream &o, const static_modint<m, (void*)nullptr> &a) { return o << a.val(); }

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

    int n, k; cin >> n >> k;
    auto graph = vector2<int>(n, 0);
    for(int i = 0; i < n-1; i++){
        int u, v; cin >> u >> v;
        u--; v--;
        graph[u].emplace_back(v);
        graph[v].emplace_back(u);
    }

    auto dfs = [&](auto &&dfs, int now, int par) -> vector<vector<mint>> {
        auto dp = vector2<mint>(2, 2, 0);
        dp[0][0] = 1, dp[1][1] = 1;

        for(auto chd : graph[now]){
            if(chd == par) continue;

            auto ret = dfs(dfs, chd, now);
            int ndp_size = min(k+1, (int)((int)dp[0].size() + (int)ret[0].size() - 1));
            auto ndp = vector2<mint>(2, ndp_size, 0);
            for(int i = 0; i < dp[0].size(); i++){
                for(int j = 0; j < ret[0].size() && i+j < k+3; j++){
                    if(i+j < ndp[0].size()) ndp[0][i+j] += dp[0][i] * (ret[0][j] + ret[1][j]);
                    if(i+j < ndp[0].size()) ndp[1][i+j] += dp[1][i] * (ret[0][j] + ret[1][j]);
                    if(i+j-1 >= 0 && i+j-1 < ndp[0].size()) ndp[1][i+j-1] += dp[1][i] * ret[1][j];
                }
            }
            dp = std::move(ndp);
        }

        return dp;
    };

    auto ans = dfs(dfs, 0, -1);
    cout << ans[0][k] + ans[1][k] << endl;
    return 0;
}
accuracy: 1
time_ms: 370
memory_kb: 31720
final_rank: 1

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

using namespace std;

using ll = long long;
const ll MOD = 998244353;

int f(int x){
  x %= MOD;
  x += MOD;
  x %= MOD;
  return x;
}


ll modadd(ll a,ll b){
  return f(a + b);
}
ll modmul(ll a,ll b){
  return f(a * b);
}

ll func(){
  int n;
  int k;
  cin >> n >> k;
  vector<vector<int>> edges(n);
  for(int i=0;i<n-1;++i){
    int a;
    int b;
    cin >> a >> b;
    --a;
    --b;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }
  vector<vector<vector<ll>>> dp(2,vector<vector<ll>>(k+1,vector<ll>(n,-1)));
  auto rec = [&](auto rec,int p,int k,bool has_parent,int last) -> ll {
    auto &it = dp[has_parent][k][p];
    if(it >= 0)return it;
    it = 0;
    vector<vector<ll>> np;
    vector<vector<ll>> hp;
    {
      for(auto e:edges[p]){
        if(e == last)continue;
        vector<ll> addn;
        vector<ll> addh;
        for(int i=0;i<=k;++i){
          addn.push_back(rec(rec,e,i,false,p));
          addh.push_back(rec(rec,e,i,true,p));
        }
        np.push_back(addn);
        hp.push_back(addh);
      }
    }
    { 
      // unuse this vertex
      vector<ll> dp(k+1,0);
      dp[0] = 1;
      for(auto i:np){
        vector<ll> dp2(k+1,0);
        for(int j=0;j<=k;++j){
          for(int l=0;j+l<=k;++l){
            dp2[j+l] = modadd(dp2[j+l], modmul(dp[j], i[l]));
          }
        }
        swap(dp, dp2);
      }
      it = modadd(it, dp[k]);
    }
    {
      // use this vertex
      vector<ll> dp(k+1,0);
      dp[0] = 1;
      for(auto i:hp){
        vector<ll> dp2(k+1,0);
        for(int j=0;j<=k;++j){
          for(int l=0;j+l<=k;++l){
            dp2[j+l] = modadd(dp2[j+l], modmul(dp[j], i[l]));
          }
        }
        swap(dp, dp2);
      }
      // cut to parent
      if(k >= 1){
        it = modadd(it, dp[k-1]);
      }
      // connect to parent
      if(has_parent){
        it = modadd(it, dp[k]);
      }
    }
    return it;
  };
  return rec(rec, 0, k, false, -1);
}

int main(){
  cout << func() << endl;
}
accuracy: 0.08333333333333333
time_ms: 40
memory_kb: 3536
final_rank: 20

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


#include <utility>

namespace atcoder {

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;
    for (long long a : {2, 7, 61}) {
        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;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

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);

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

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<(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

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

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>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::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 = internal::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 = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::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 = internal::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 internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::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>;

}  // namespace internal

}  // namespace atcoder

using namespace atcoder;
using mint = modint998244353;
//using mint = modint1000000007;
#pragma region template
using ll = long long;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep(...) overload3(__VA_ARGS__,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define debug(var)  do{std::cerr << #var << " : ";view(var);}while(0)
template<typename T> void view(T e){std::cerr << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cerr << e << " "; } std::cerr << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){cerr << endl;int cnt = 0;for(const auto& v : vv){cerr << cnt << "th : "; view(v); cnt++;} cerr << endl;}
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
  std::ostream::sentry s(dest);
  if (s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
template<class T, class K>bool chmax(T &a, const K b) { if (a<b) { a=b; return 1; } return 0; }
template<class T, class K>bool chmin(T &a, const K b) { if (b<a) { a=b; return 1; } return 0; }
const int inf = 1001001001;
const ll INF = 1001001001001001001ll;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
ll rddiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // -20 / 3 == -7
ll power(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a;} a = a * a; p >>= 1;} return ret;}
ll modpow(ll a, ll p, ll mod){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}
ll rudiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } //  20 / 3 == 7
#pragma endregion
// const double pi = acos(-1);
//const ll mod = 998244353;
//const ll mod = 1000000007;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(20);
    int n, k; cin >> n >> k;
    VV<int> G(n);
    rep(i,n-1){
        int a, b; cin >> a >> b;
        G[--a].pb(--b);
        G[b].pb(a);
    }
    VV<V<mint>> dp(n);
    auto dfs = [&](auto self, int v = 0, int p = -1)->void{
        VV<mint> res(2,V<mint>(2));
        res[0][0] = res[1][1] = 1;
        for(int nv : G[v]){
            if(nv == p) continue;
            self(self, nv, v);
            VV<mint> merged(min(k + 1, sz(dp[nv]) + sz(res) - 1), V<mint>(2));
            for(int i = 0; i < sz(res); i++){
                for(int j = 0; j < sz(dp[nv]); j++){
                    if(i + j > k) break;
                    merged[i + j][0] = (merged[i + j][0] + res[i][0] * (dp[nv][j][0] + dp[nv][j][1]));
                    merged[i + j][1] = (merged[i + j][1] + res[i][1] * (dp[nv][j][0] + dp[nv][j][1]));
                    if(j + 1 < sz(dp[nv])) merged[i + j][1] += res[i][1] * dp[nv][j + 1][1];
                }
            }
            swap(res, merged);
            {
                VV<mint> tmp;
                swap(tmp, dp[nv]);
            }
        }
        swap(dp[v], res);
    };
    dfs(dfs);
    cout << (dp[0][k][0] + dp[0][k][1]).val() << endl;
}
accuracy: 1
time_ms: 1160
memory_kb: 35012
final_rank: 2

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


#include <utility>

namespace atcoder {

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;
    for (long long a : {2, 7, 61}) {
        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;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

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);

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

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<(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

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

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>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::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 = internal::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 = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::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 = internal::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 internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::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>;

}  // namespace internal

}  // namespace atcoder

using namespace atcoder;
using mint = modint998244353;
//using mint = modint1000000007;
#pragma region template
using ll = long long;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep(...) overload3(__VA_ARGS__,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define debug(var)  do{std::cerr << #var << " : ";view(var);}while(0)
template<typename T> void view(T e){std::cerr << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cerr << e << " "; } std::cerr << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){cerr << endl;int cnt = 0;for(const auto& v : vv){cerr << cnt << "th : "; view(v); cnt++;} cerr << endl;}
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
  std::ostream::sentry s(dest);
  if (s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
template<class T, class K>bool chmax(T &a, const K b) { if (a<b) { a=b; return 1; } return 0; }
template<class T, class K>bool chmin(T &a, const K b) { if (b<a) { a=b; return 1; } return 0; }
const int inf = 1001001001;
const ll INF = 1001001001001001001ll;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
ll rddiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // -20 / 3 == -7
ll power(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a;} a = a * a; p >>= 1;} return ret;}
ll modpow(ll a, ll p, ll mod){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}
ll rudiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } //  20 / 3 == 7
#pragma endregion
// const double pi = acos(-1);
//const ll mod = 998244353;
//const ll mod = 1000000007;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(20);
    int n, k; cin >> n >> k;
    VV<int> G(n);
    rep(i,n-1){
        int a, b; cin >> a >> b;
        G[--a].pb(--b);
        G[b].pb(a);
    }
    VV<V<mint>> dp(n);
    auto dfs = [&](auto self, int v = 0, int p = -1)->void{
        VV<mint> res(2,V<mint>(2));
        res[0][0] = res[1][1] = 1;
        for(int nv : G[v]){
            if(nv == p) continue;
            self(self, nv, v);
            VV<mint> merged(min(k + 1, sz(dp[nv]) + sz(res) - 1), V<mint>(2));
            for(int i = 0; i < sz(res); i++){
                for(int j = 0; j < sz(dp[nv]); j++){
                    if(i + j > k) break;
                    merged[i + j][0] = (merged[i + j][0] + res[i][0] * (dp[nv][j][0] + dp[nv][j][1]));
                    merged[i + j][1] = (merged[i + j][1] + res[i][1] * (dp[nv][j][0] + dp[nv][j][1]));
                    if(j + 1 < sz(dp[nv])) merged[i + j][1] += res[i][1] * dp[nv][j + 1][1];
                }
            }
            swap(res, merged);
            {
                VV<mint> k;
                swap(dp[nv], k);
            }
        }
        dp[v] = res;
    };
    dfs(dfs);
    cout << (dp[0][k][0] + dp[0][k][1]).val() << endl;
}
accuracy: 1
time_ms: 1930
memory_kb: 36184
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
//#include <atcoder/modint>
//using namespace atcoder;
//using mint = modint998244353;
//using mint = modint1000000007;
#pragma region template
using ll = long long;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep(...) overload3(__VA_ARGS__,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define debug(var)  do{std::cerr << #var << " : ";view(var);}while(0)
template<typename T> void view(T e){std::cerr << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cerr << e << " "; } std::cerr << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){cerr << endl;int cnt = 0;for(const auto& v : vv){cerr << cnt << "th : "; view(v); cnt++;} cerr << endl;}
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
  std::ostream::sentry s(dest);
  if (s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
template<class T, class K>bool chmax(T &a, const K b) { if (a<b) { a=b; return 1; } return 0; }
template<class T, class K>bool chmin(T &a, const K b) { if (b<a) { a=b; return 1; } return 0; }
const int inf = 1001001001;
const ll INF = 1001001001001001001ll;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
ll rddiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // -20 / 3 == -7
ll power(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a;} a = a * a; p >>= 1;} return ret;}
ll modpow(ll a, ll p, ll mod){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}
ll rudiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } //  20 / 3 == 7
#pragma endregion
// const double pi = acos(-1);
const ll mod = 998244353;
//const ll mod = 1000000007;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(20);
    int n, k; cin >> n >> k;
    VV<int> G(n);
    rep(i,n-1){
        int a, b; cin >> a >> b;
        G[--a].pb(--b);
        G[b].pb(a);
    }
    VV<V<ll>> dp(n);
    auto dfs = [&](auto self, int v = 0, int p = -1)->void{
        VV<ll> res(2,V<ll>(2));
        res[0][0] = res[1][1] = 1;
        for(int nv : G[v]){
            if(nv == p) continue;
            self(self, nv, v);
            VV<ll> merged(min(k + 1, sz(dp[nv]) + sz(res) - 1), V<ll>(2));
            for(int i = 0; i < sz(res); i++){
                for(int j = 0; j < sz(dp[nv]); j++){
                    if(i + j > k) break;
                    merged[i + j][0] = (merged[i + j][0] + res[i][0] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    merged[i + j][1] = (merged[i + j][1] + res[i][1] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    if(j + 1 < sz(dp[nv])) merged[i + j][1] += res[i][1] * dp[nv][j + 1][1] % mod, merged[i + j][1] %= mod;
                }
            }
            swap(res, merged);
            {
                VV<ll> k;
                swap(dp[nv], k);
            }
        }
        dp[v] = res;
    };
    dfs(dfs);
    cout << (dp[0][k][0] + dp[0][k][1]) % mod << endl;
}
accuracy: 1
time_ms: 2060
memory_kb: 36076
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
//#include <atcoder/modint>
//using namespace atcoder;
//using mint = modint998244353;
//using mint = modint1000000007;
#pragma region template
using ll = long long;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep(...) overload3(__VA_ARGS__,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define debug(var)  do{std::cerr << #var << " : ";view(var);}while(0)
template<typename T> void view(T e){std::cerr << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cerr << e << " "; } std::cerr << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){cerr << endl;int cnt = 0;for(const auto& v : vv){cerr << cnt << "th : "; view(v); cnt++;} cerr << endl;}
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
  std::ostream::sentry s(dest);
  if (s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
template<class T, class K>bool chmax(T &a, const K b) { if (a<b) { a=b; return 1; } return 0; }
template<class T, class K>bool chmin(T &a, const K b) { if (b<a) { a=b; return 1; } return 0; }
const int inf = 1001001001;
const ll INF = 1001001001001001001ll;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
ll rddiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // -20 / 3 == -7
ll power(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a;} a = a * a; p >>= 1;} return ret;}
ll modpow(ll a, ll p, ll mod){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}
ll rudiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } //  20 / 3 == 7
#pragma endregion
// const double pi = acos(-1);
const ll mod = 998244353;
//const ll mod = 1000000007;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(20);
    int n, k; cin >> n >> k;
    VV<int> G(n);
    rep(i,n-1){
        int a, b; cin >> a >> b;
        G[--a].pb(--b);
        G[b].pb(a);
    }
    VV<V<ll>> dp(n);
    auto dfs = [&](auto self, int v = 0, int p = -1)->void{
        VV<ll> res(2,V<ll>(2));
        res[0][0] = res[1][1] = 1;
        for(int nv : G[v]){
            if(nv == p) continue;
            self(self, nv, v);
            VV<ll> merged(sz(dp[nv]) + sz(res) - 1, V<ll>(2));
            for(int i = 0; i < sz(res); i++){
                for(int j = 0; j < sz(dp[nv]); j++){
                    if(i + j > k) break;
                    merged[i + j][0] = (merged[i + j][0] + res[i][0] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    merged[i + j][1] = (merged[i + j][1] + res[i][1] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    if(j + 1 < sz(dp[nv])) merged[i + j][1] += res[i][1] * dp[nv][j + 1][1] % mod, merged[i + j][1] %= mod;
                }
            }
            swap(res, merged);
            if(sz(res) >= k + 1) res.resize(k + 1);
            {
                VV<ll> k;
                swap(dp[nv], k);
            }
        }
        dp[v] = res;
    };
    dfs(dfs);
    cout << (dp[0][k][0] + dp[0][k][1]) % mod << endl;
}
accuracy: 1
time_ms: 2110
memory_kb: 38696
final_rank: 5

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

// modint
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() const { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    constexpr bool operator < (const Fp& r) const noexcept {
        return this->val < r.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

const int MOD = 998244353;
using mint = Fp<MOD>;
using pint = pair<mint,mint>;
using Graph = vector<vector<int>>;

int N, K;
vector<vector<pint>> dp; // (v nonuse, v use)
void rec(const Graph &G, int v, int p = -1) {
    for (auto c : G[v]) {
        if (c == p) continue;
        rec(G, c, v);
    }
    vector<pint> dp2(2), ndp2;
    dp2[0] = {1, 0}, dp2[1] = {0, 1};
    for (auto c : G[v]) {
        if (c == p) continue;
        int S = min(K+1, (int)(dp2.size()+dp[c].size()));
        ndp2.assign(S, pint(0, 0));
        for (int i = 0; i < dp2.size(); ++i) {
            for (int j = 0; j < dp[c].size() && i+j-1 <= K; ++j) {
                if (i+j <= K) {
                    ndp2[i+j].first += dp2[i].first * (dp[c][j].first + dp[c][j].second);
                    ndp2[i+j].second += dp2[i].second * (dp[c][j].first + dp[c][j].second);
                }
                if (i+j-1>=0) {
                    ndp2[i+j-1].second += dp2[i].second * dp[c][j].second;
                }
            }
        }
        swap(dp2, ndp2);
    }
    dp[v] = dp2;
}

int main() {
    cin >> N >> K;
    Graph G(N);
    for (int i = 0; i < N-1; ++i) {
        int x, y; cin >> x >> y; --x, --y;
        G[x].push_back(y), G[y].push_back(x);
    }
    dp.assign(N, vector<pint>());
    rec(G, 0);
    cout << dp[0][K].first + dp[0][K].second << endl;
}
accuracy: 1
time_ms: 490
memory_kb: 495840
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
//#include <atcoder/modint>
//using namespace atcoder;
//using mint = modint998244353;
//using mint = modint1000000007;
#pragma region template
using ll = long long;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep(...) overload3(__VA_ARGS__,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define debug(var)  do{std::cerr << #var << " : ";view(var);}while(0)
template<typename T> void view(T e){std::cerr << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cerr << e << " "; } std::cerr << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){cerr << endl;int cnt = 0;for(const auto& v : vv){cerr << cnt << "th : "; view(v); cnt++;} cerr << endl;}
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
  std::ostream::sentry s(dest);
  if (s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
template<class T, class K>bool chmax(T &a, const K b) { if (a<b) { a=b; return 1; } return 0; }
template<class T, class K>bool chmin(T &a, const K b) { if (b<a) { a=b; return 1; } return 0; }
const int inf = 1001001001;
const ll INF = 1001001001001001001ll;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
ll rddiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // -20 / 3 == -7
ll power(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a;} a = a * a; p >>= 1;} return ret;}
ll modpow(ll a, ll p, ll mod){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}
ll rudiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } //  20 / 3 == 7
#pragma endregion
// const double pi = acos(-1);
const ll mod = 998244353;
//const ll mod = 1000000007;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(20);
    int n, k; cin >> n >> k;
    VV<int> G(n);
    rep(i,n-1){
        int a, b; cin >> a >> b;
        G[--a].pb(--b);
        G[b].pb(a);
    }
    VV<V<ll>> dp(n);
    auto dfs = [&](auto self, int v = 0, int p = -1)->void{
        VV<ll> res(2,V<ll>(2));
        res[0][0] = res[1][1] = 1;
        for(int nv : G[v]){
            if(nv == p) continue;
            self(self, nv, v);
            VV<ll> merged(sz(dp[nv]) + sz(res) - 1, V<ll>(2));
            for(int i = 0; i < sz(res); i++){
                for(int j = 0; j < sz(dp[nv]); j++){
                    if(i + j > k) break;
                    merged[i + j][0] = (merged[i + j][0] + res[i][0] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    merged[i + j][1] = (merged[i + j][1] + res[i][1] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    if(j + 1 < sz(dp[nv])) merged[i + j][1] += res[i][1] * dp[nv][j + 1][1] % mod, merged[i + j][1] %= mod;
                }
            }
            res = merged;
            if(sz(merged) >= k + 1) res.resize(k + 1);
            {
                VV<ll> k;
                swap(dp[nv], k);
            }
        }
        dp[v] = res;
    };
    dfs(dfs);
    cout << (dp[0][k][0] + dp[0][k][1]) % mod << endl;
}
accuracy: 1
time_ms: 2800
memory_kb: 36168
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
//#include <atcoder/modint>
//using namespace atcoder;
//using mint = modint998244353;
//using mint = modint1000000007;
#pragma region template
using ll = long long;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep(...) overload3(__VA_ARGS__,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define debug(var)  do{std::cerr << #var << " : ";view(var);}while(0)
template<typename T> void view(T e){std::cerr << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cerr << e << " "; } std::cerr << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){cerr << endl;int cnt = 0;for(const auto& v : vv){cerr << cnt << "th : "; view(v); cnt++;} cerr << endl;}
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
  std::ostream::sentry s(dest);
  if (s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
template<class T, class K>bool chmax(T &a, const K b) { if (a<b) { a=b; return 1; } return 0; }
template<class T, class K>bool chmin(T &a, const K b) { if (b<a) { a=b; return 1; } return 0; }
const int inf = 1001001001;
const ll INF = 1001001001001001001ll;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
ll rddiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // -20 / 3 == -7
ll power(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a;} a = a * a; p >>= 1;} return ret;}
ll modpow(ll a, ll p, ll mod){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}
ll rudiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } //  20 / 3 == 7
#pragma endregion
// const double pi = acos(-1);
const ll mod = 998244353;
//const ll mod = 1000000007;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(20);
    int n, k; cin >> n >> k;
    VV<int> G(n);
    rep(i,n-1){
        int a, b; cin >> a >> b;
        G[--a].pb(--b);
        G[b].pb(a);
    }
    VV<V<ll>> dp(n);
    auto dfs = [&](auto self, int v = 0, int p = -1)->void{
        VV<ll> res(2,V<ll>(2));
        res[0][0] = res[1][1] = 1;
        for(int nv : G[v]){
            if(nv == p) continue;
            self(self, nv, v);
            VV<ll> merged(sz(dp[nv]) + sz(res) - 1, V<ll>(2));
            for(int i = 0; i < sz(res); i++){
                for(int j = 0; j < sz(dp[nv]); j++){
                    merged[i + j][0] = (merged[i + j][0] + res[i][0] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    merged[i + j][1] = (merged[i + j][1] + res[i][1] * (dp[nv][j][0] + dp[nv][j][1]) % mod) % mod;
                    if(j + 1 < sz(dp[nv])) merged[i + j][1] += res[i][1] * dp[nv][j + 1][1] % mod, merged[i + j][1] %= mod;
                }
            }
            res = merged;
            if(sz(merged) >= k + 1) res.resize(k + 1);
            {
                VV<ll> k;
                swap(dp[nv], k);
            }
        }
        dp[v] = res;
    };
    dfs(dfs);
    cout << (dp[0][k][0] + dp[0][k][1]) % mod << endl;
}
accuracy: 1
time_ms: 2850
memory_kb: 36196
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#include <sys/time.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }

// modint
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() const { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    constexpr bool operator < (const Fp& r) const noexcept {
        return this->val < r.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

const int MOD = 998244353;
using mint = Fp<MOD>;
using pint = pair<mint,mint>;
using Graph = vector<vector<int>>;

int N, K;
vector<vector<pint>> dp; // (v nonuse, v use)
void rec(const Graph &G, int v, int p = -1) {
    for (auto c : G[v]) {
        if (c == p) continue;
        rec(G, c, v);
    }
    vector<pint> dp2(2), ndp2;
    dp2[0] = {1, 0}, dp2[1] = {0, 1};
    for (auto c : G[v]) {
        if (c == p) continue;
        int S = min(K+1, (int)(dp2.size()+dp[c].size()));
        ndp2.assign(S, pint(0, 0));
        for (int i = 0; i < dp2.size(); ++i) {
            for (int j = 0; j < dp[c].size() && i+j-1 <= K; ++j) {
                if (i+j <= K) {
                    ndp2[i+j].first += dp2[i].first * (dp[c][j].first + dp[c][j].second);
                    ndp2[i+j].second += dp2[i].second * (dp[c][j].first + dp[c][j].second);
                }
                if (i+j-1>=0) {
                    ndp2[i+j-1].second += dp2[i].second * dp[c][j].second;
                }
            }
        }
        swap(dp2, ndp2);
    }
    dp[v] = dp2;
    //cout << v << ": " << dp[v] << endl;
}

int main() {
    cin >> N >> K;
    Graph G(N);
    for (int i = 0; i < N-1; ++i) {
        int x, y; cin >> x >> y; --x, --y;
        G[x].push_back(y), G[y].push_back(x);
    }
    dp.assign(N, vector<pint>());
    rec(G, 0);
    cout << dp[0][K].first + dp[0][K].second << endl;
}
accuracy: 1
time_ms: 480
memory_kb: 495860
final_rank: 9

code_snippet: #include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 998244353
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto& (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define sar(a,n) {cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl;}

using namespace std;

template<typename S,typename T>auto&operator<<(ostream&o,pair<S,T>p){return o<<"{"<<p.fi<<","<<p.se<<"}";}
template<typename T>auto&operator<<(ostream&o,set<T>s){for(auto&e:s)o<<e<<" ";return o;}
template<typename S,typename T,typename U>
auto&operator<<(ostream&o,priority_queue<S,T,U>q){while(!q.empty())o<<q.top()<<" ",q.pop();return o;}
template<typename K,typename T>auto&operator<<(ostream&o,map<K,T>&m){for(auto&e:m)o<<e<<" ";return o;}
template<typename T>auto&operator<<(ostream&o,vector<T>v){for(auto&e:v)o<<e<<" ";return o;}
void ashow(){cout<<endl;}template<typename T,typename...A>void ashow(T t,A...a){cout<<t<<" ";ashow(a...);}
template<typename S,typename T,typename U>
struct TRI{S fi;T se;U th;TRI(){}TRI(S f,T s,U t):fi(f),se(s),th(t){}
bool operator<(const TRI&_)const{return(fi==_.fi)?((se==_.se)?(th<_.th):(se<_.se)):(fi<_.fi);}};
template<typename S,typename T,typename U>
auto&operator<<(ostream&o,TRI<S,T,U>&t){return o<<"{"<<t.fi<<","<<t.se<<","<<t.th<<"}";}

typedef pair<int, int> P;
typedef pair<ll, ll> pll;
typedef TRI<int, int, int> tri;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef vector<P> vp;
typedef vector<double> vd;
typedef vector<string> vs;

template <unsigned int mod>
class ModInt {
private:
    unsigned int v;
    static unsigned int norm(const unsigned int& x){ return x < mod ? x : x - mod; }
	static ModInt make(const unsigned int& x){ ModInt m; return m.v = x, m; }
    static ModInt inv(const ModInt& x){ return make(inverse(x.v, mod)); }
    static unsigned int inverse(int a, int m){
        int u[] = {a, 1, 0}, v[] = {m, 0, 1}, t;
        while(*v){
            t = *u / *v;
            swap(u[0] -= t * v[0], v[0]), swap(u[1] -= t * v[1], v[1]), swap(u[2] -= t * v[2], v[2]);
        }
        return (u[1] % m + m) % m;
    }

public:
    ModInt() : v{0}{}
    ModInt(const long long val) : v{norm(val % mod + mod)} {}
    ModInt(const ModInt<mod>& n) : v{n()} {}
	explicit operator bool() const noexcept { return v != 0; }
    bool operator!() const noexcept { return !static_cast<bool>(*this); }
    ModInt& operator=(const ModInt& n){ return v = n(), (*this); }
    ModInt& operator=(const long long val){ return v = norm(val % mod + mod), (*this); }
    ModInt operator+() const { return *this; }
    ModInt operator-() const { return v == 0 ? make(0) : make(mod - v); }
    ModInt operator+(const ModInt& val) const { return make(norm(v + val())); }
    ModInt operator-(const ModInt& val) const { return make(norm(v + mod - val())); }
    ModInt operator*(const ModInt& val) const { return make((long long)v * val() % mod); }
    ModInt operator/(const ModInt& val) const { return *this * inv(val); }
    ModInt& operator+=(const ModInt& val){ return *this = *this + val; }
    ModInt& operator-=(const ModInt& val){ return *this = *this - val; }
    ModInt& operator*=(const ModInt& val){ return *this = *this * val; }
    ModInt& operator/=(const ModInt& val){ return *this = *this / val; }
    ModInt operator+(const long long val) const { return ModInt{v + val}; }
    ModInt operator-(const long long val) const { return ModInt{v - val}; }
    ModInt operator*(const long long val) const { return ModInt{(long long)v * (val % mod)}; }
    ModInt operator/(const long long val) const { return ModInt{(long long)v * inv(val)}; }
    ModInt& operator+=(const long long val){ return *this = *this + val; }
    ModInt& operator-=(const long long val){ return *this = *this - val; }
    ModInt& operator*=(const long long val){ return *this = *this * val; }
    ModInt& operator/=(const long long val){ return *this = *this / val; }
    bool operator==(const ModInt& val) const { return v == val.v; }
    bool operator!=(const ModInt& val) const { return !(*this == val); }
    bool operator==(const long long val) const { return v == norm(val % mod + mod); }
    bool operator!=(const long long val) const { return !(*this == val); }
    unsigned int operator()() const { return v; }
    friend ModInt operator+(const long long val, const ModInt& n) { return n + val; }
    friend ModInt operator-(const long long val, const ModInt& n) { return ModInt{val - n()}; }
    friend ModInt operator*(const long long val, const ModInt& n) { return n * val; }
    friend ModInt operator/(const long long val, const ModInt& n) { return ModInt{val} / n; }
    friend bool operator==(const long long val, const ModInt& n) { return n == val; }
    friend bool operator!=(const long long val, const ModInt& n) { return !(val == n); }
    friend istream& operator>>(istream& is, ModInt& n){
        unsigned int v;
        return is >> v, n = v, is;
    }
    friend ostream& operator<<(ostream& os, const ModInt& n){ return (os << n()); }
    friend ModInt mod_pow(ModInt x, long long n){
        ModInt ans = 1;
        while(n){
            if(n & 1) ans *= x;
            x *= x, n >>= 1;
        }
        return ans;
    }
};

const int MAX_N = 100005;
const int MAX_K = 305;

using mod = ModInt<MOD>;

int n, K;
vector<int> G[MAX_N];
int sz[MAX_N];
mod dp[MAX_N][MAX_K][2][2];

void dfs(int u, int p)
{
    sz[u] = 1;
    dp[u][0][0][0] = dp[u][1][1][0] = 1;
    for(int v : G[u]){
        if(v != p){
            dfs(v, u);
            rep(i,sz[u]+1){
                rep(j,sz[v]+1){
                    // ある場合
                    if(i + j > 0) dp[u][i+j-1][1][1] += dp[u][i][1][0] * dp[v][j][1][0];
                    if(i + j == K + 1) break;
                    // 無い場合
                    dp[u][i+j][0][1] += dp[u][i][0][0] * (dp[v][j][0][0] + dp[v][j][1][0]);
                    // dp[u][i+j][1][1] += dp[u][i][0][0] * dp[v][j][1][0];
                    // ある場合
                    dp[u][i+j][1][1] += dp[u][i][1][0] * (dp[v][j][0][0] + dp[v][j][1][0]);
                }
            }
            sz[u] = min(sz[u] + sz[v], K);
            rep(i,sz[u]+1){ rep(j,2) dp[u][i][j][0] = dp[u][i][j][1], dp[u][i][j][1] = 0; }
        }
    }
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> n >> K;
    rep(i,n-1){
        int u, v;
        cin >> u >> v;
        --u, --v;
        G[u].pb(v), G[v].pb(u);
    }
    dfs(0, -1);
    cout << dp[0][K][0][0] + dp[0][K][1][0] << "\n";
    return 0;
}
accuracy: 1
time_ms: 630
memory_kb: 495988
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


struct FastIO{
  FastIO(){
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
}fastio_beet;


template<typename F>
struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args>
  decltype(auto) operator()(Args&&... args) const{
    return F::operator()(*this,forward<Args>(args)...);
  }
};
template<typename F>
inline decltype(auto) MFP(F&& f){
  return FixPoint<F>{forward<F>(f)};
}


template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;};
  Mint operator-(Mint a) const{return Mint(v)-=a;};
  Mint operator*(Mint a) const{return Mint(v)*=a;};
  Mint operator/(Mint a) const{return Mint(v)/=a;};

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}

//INSERT ABOVE HERE
signed main(){
  Int n,k;
  cin>>n>>k;
  vector< vector<Int> > G(n);
  for(Int i=1;i<n;i++){
    Int u,v;
    cin>>u>>v;
    u--;v--;
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }
  using M = Mint<Int, 998244353>;
  vector< vector<M> > dp1(n); // connected to v
  vector< vector<M> > dp2(n); // not connected

  vector<Int> sz(n);
  MFP([&](auto dfs,Int v,Int p)->void{
        sz[v]=1;
        dp1[v].assign(sz[v]+1,M(0));
        dp2[v].assign(sz[v]+1,M(0));
        dp1[v][1]=M(1);
        dp2[v][0]=M(1);

        for(Int u:G[v]){
          if(u==p) continue;
          dfs(u,v);
          vector<M> nx1(sz[v]+sz[u]+1);
          vector<M> nx2(sz[v]+sz[u]+1);
          for(Int i=0;i<=sz[v];i++){
            for(Int j=0;j<=sz[u];j++){
              // cut
              nx1[i+j]+=dp1[v][i]*dp1[u][j];
              nx1[i+j]+=dp1[v][i]*dp2[u][j];
              nx2[i+j]+=dp2[v][i]*dp1[u][j];
              nx2[i+j]+=dp2[v][i]*dp2[u][j];

              // link
              if(i+j>0) nx1[i+j-1]+=dp1[v][i]*dp1[u][j];
            }
          }
          sz[v]+=sz[u];
          dp1[v]=nx1;
          dp2[v]=nx2;
          if(sz[v]>k){
            sz[v]=k;
            dp1[v].resize(k+1);
            dp2[v].resize(k+1);
          }
        }
      })(0,-1);

  cout<<dp1[0][k]+dp2[0][k]<<endl;
  return 0;
}
accuracy: 1
time_ms: 1720
memory_kb: 507060
final_rank: 19

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
//#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define MOD 998244353
#define SIZE 100005

enum Type{
	USE,
	NOT,
};

ll N,K;
ll dp[SIZE][305][2],work[305][2];
ll num_nodes[SIZE];
vector<int> G[SIZE];


void dfs(int node_id,int parent){

	//dp[頂点番号(=k)][kの部分木の分割数][kを使用しているかどうか] = 場合の数
	dp[node_id][1][USE] = 1;
	dp[node_id][0][NOT] = 1;
	num_nodes[node_id] = 1;

	for(int i = 0; i < G[node_id].size(); i++){

		int child = G[node_id][i];
		if(child == parent)continue;

		dfs(child,node_id);

		for(int a = 0; a <= K; a++){
			work[a][USE] = 0;
			work[a][NOT] = 0;
		}

		for(int a = 0; a <= min(num_nodes[node_id],K+1); a++){
			for(int b = 0; b <= min(num_nodes[child],K+1-a); b++){

				work[a+b][USE] += dp[node_id][a][USE]*dp[child][b][USE];
				work[a+b][USE] %= MOD;
				work[a+b][USE] += dp[node_id][a][USE]*dp[child][b][NOT];
				work[a+b][USE] %= MOD;

				work[a+b][NOT] += dp[node_id][a][NOT]*dp[child][b][USE];
				work[a+b][NOT] %= MOD;
				work[a+b][NOT] += dp[node_id][a][NOT]*dp[child][b][NOT];
				work[a+b][NOT] %= MOD;

				if(a+b > 0){
					//node_idとchildを同時に含むグループを作る
					work[a+b-1][USE] += dp[node_id][a][USE]*dp[child][b][USE];
					work[a+b-1][USE] %= MOD;
				}
			}
		}

		num_nodes[node_id] += num_nodes[child];

		for(int a = 0; a <= min(num_nodes[node_id],K+1); a++){

			dp[node_id][a][USE] = work[a][USE];
			dp[node_id][a][NOT] = work[a][NOT];
		}
	}
}


int main(){

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

	int from,to;
	for(int loop = 0; loop < N-1; loop++){

		scanf("%d %d",&from,&to);
		from--;
		to--;

		G[from].push_back(to);
		G[to].push_back(from);
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k <= K; k++){
			for(int p = 0; p < 2; p++){
				dp[i][k][p] = 0;
			}
		}
	}

	dfs(0,-1);

	printf("%lld\n",(dp[0][K][USE]+dp[0][K][NOT])%MOD);

	return 0;
}
accuracy: 1
time_ms: 560
memory_kb: 498736
final_rank: 11

code_snippet: #include "bits/stdc++.h"

using namespace std;

using ll = long long;
constexpr ll MOD = 998244353;

int n, k;
ll dp[100010][310][2];
vector<int> sub(100010, 1);
vector<vector<int>> g(100010);

void rec(int cur, int pre)
{
    dp[cur][0][0] = dp[cur][1][1] = 1;
    int ma = min(k, 1);
    for (auto v : g[cur])
    {
        if (v == pre)
            continue;
        rec(v, cur);
        sub[cur] += sub[v];
        int s = min(k, sub[v]);
        vector<ll> nxt0(min(k, ma + sub[v]) + 1, 0), nxt1(min(k, ma + sub[v]) + 1, 0);
        for (int i = 0; i <= ma; i++)
        {
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][0] % MOD;
                nxt0[i + j] = (nxt0[i + j] + sum);
                if (nxt0[i + j] >= MOD)
                    nxt0[i + j] -= MOD;
            }
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][1] % MOD;
                nxt1[i + j] = (nxt1[i + j] + sum);
                if (nxt1[i + j] >= MOD)
                    nxt1[i + j] -= MOD;
            }
            for (int j = 1; j <= s; j++)
            {
                if (i + j - 1 > k)
                    break;
                ll sum = dp[v][j][1] * dp[cur][i][1] % MOD;
                nxt1[i + j - 1] = (nxt1[i + j - 1] + sum);
                if (nxt1[i + j - 1] >= MOD)
                    nxt1[i + j - 1] -= MOD;
            }
        }
        ma = min(k, ma + sub[v]);
        for (int i = 0; i <= ma; i++)
        {
            dp[cur][i][0] = nxt0[i];
            dp[cur][i][1] = nxt1[i];
        }
    }
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> k;
    for (int i = 0; i < n - 1; i++)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    rec(0, -1);
    cout << (dp[0][k][0] + dp[0][k][1]) % MOD << endl;
}
accuracy: 1
time_ms: 720
memory_kb: 503420
final_rank: 16

code_snippet: #include "bits/stdc++.h"

using namespace std;

using ll = long long;
constexpr ll MOD = 998244353;

int n, k;
ll dp[100010][310][2];
ll nxt0[310], nxt1[310];
vector<int> sub(100010, 1);
vector<vector<int>> g(100010);

void rec(int cur, int pre)
{
    dp[cur][0][0] = dp[cur][1][1] = 1;
    int ma = min(k, 1);
    for (auto v : g[cur])
    {
        if (v == pre)
            continue;
        rec(v, cur);
        sub[cur] += sub[v];
        int s = min(k, sub[v]);
        for (int i = 0; i <= min(k, ma + sub[v]); i++)
            nxt0[i] = nxt1[i] = 0;
        for (int i = 0; i <= ma; i++)
        {
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][0] % MOD;
                nxt0[i + j] = (nxt0[i + j] + sum);
                if (nxt0[i + j] >= MOD)
                    nxt0[i + j] -= MOD;
            }
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][1] % MOD;
                nxt1[i + j] = (nxt1[i + j] + sum);
                if (nxt1[i + j] >= MOD)
                    nxt1[i + j] -= MOD;
            }
            for (int j = 1; j <= s; j++)
            {
                if (i + j - 1 > k)
                    break;
                ll sum = dp[v][j][1] * dp[cur][i][1] % MOD;
                nxt1[i + j - 1] = (nxt1[i + j - 1] + sum);
                if (nxt1[i + j - 1] >= MOD)
                    nxt1[i + j - 1] -= MOD;
            }
        }
        ma = min(k, ma + sub[v]);
        for (int i = 0; i <= ma; i++)
        {
            dp[cur][i][0] = nxt0[i];
            dp[cur][i][1] = nxt1[i];
        }
    }
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> k;
    for (int i = 0; i < n - 1; i++)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    rec(0, -1);
    cout << (dp[0][k][0] + dp[0][k][1]) % MOD << endl;
}
accuracy: 1
time_ms: 760
memory_kb: 502276
final_rank: 17

code_snippet: #include "bits/stdc++.h"

using namespace std;

using ll = long long;
constexpr ll MOD = 998244353;

int n, k;
ll dp[100010][310][2];
vector<int> sub(100010, 1);
vector<vector<int>> g(100010);

void rec(int cur, int pre)
{
    dp[cur][0][0] = dp[cur][1][1] = 1;
    int ma = min(k, 1);
    for (auto v : g[cur])
    {
        if (v == pre)
            continue;
        rec(v, cur);
        sub[cur] += sub[v];
        int s = min(k, sub[v]);
        vector<ll> nxt0(min(k, ma + sub[v]) + 1, 0), nxt1(min(k, ma + sub[v]) + 1, 0);
        for (int i = 0; i <= ma; i++)
        {
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][0] % MOD;
                nxt0[i + j] = (nxt0[i + j] + sum) % MOD;
            }
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][1] % MOD;
                nxt1[i + j] = (nxt1[i + j] + sum) % MOD;
            }
            for (int j = 1; j <= s; j++)
            {
                if (i + j - 1 > k)
                    break;
                ll sum = dp[v][j][1] * dp[cur][i][1] % MOD;
                nxt1[i + j - 1] = (nxt1[i + j - 1] + sum) % MOD;
            }
        }
        ma = min(k, ma + sub[v]);
        for(int i=0;i<=ma;i++)
        {
            dp[cur][i][0] = nxt0[i];
            dp[cur][i][1] = nxt1[i];
        }
    }
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> k;
    for (int i = 0; i < n - 1; i++)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    rec(0, -1);
    cout << (dp[0][k][0] + dp[0][k][1]) % MOD << endl;
}
accuracy: 1
time_ms: 630
memory_kb: 503260
final_rank: 14

code_snippet: #include "bits/stdc++.h"

using namespace std;

using ll = long long;
constexpr ll MOD = 998244353;

int n, k;
ll dp[100010][310][2];
vector<int> sub(100010, 1);
vector<vector<int>> g(100010);

ll subrec(int cur, int pre)
{
    for (auto v : g[cur])
    {
        if (v == pre)
            continue;
        sub[cur] += subrec(v, cur);
    }
    return sub[cur];
}

void rec(int cur, int pre)
{
    dp[cur][0][0] = dp[cur][1][1] = 1;
    int ma = min(k, 1);
    for (auto v : g[cur])
    {
        if (v == pre)
            continue;
        rec(v, cur);
        int s = min(k, sub[v]);
        vector<ll> nxt0(min(k, ma + sub[v]) + 1, 0), nxt1(min(k, ma + sub[v]) + 1, 0);
        for (int i = 0; i <= ma; i++)
        {
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][0] % MOD;
                nxt0[i + j] = (nxt0[i + j] + sum) % MOD;
            }
            for (int j = 0; j <= s; j++)
            {
                if (i + j > k)
                    break;
                ll sum = (dp[v][j][0] + dp[v][j][1]) * dp[cur][i][1] % MOD;
                nxt1[i + j] = (nxt1[i + j] + sum) % MOD;
            }
            for (int j = 1; j <= s; j++)
            {
                if (i + j - 1 > k)
                    break;
                ll sum = dp[v][j][1] * dp[cur][i][1] % MOD;
                nxt1[i + j - 1] = (nxt1[i + j - 1] + sum) % MOD;
            }
        }
        ma = min(k, ma + sub[v]);
        for(int i=0;i<=ma;i++)
        {
            dp[cur][i][0] = nxt0[i];
            dp[cur][i][1] = nxt1[i];
        }
    }
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> k;
    for (int i = 0; i < n - 1; i++)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    subrec(0, -1);
    rec(0, -1);
    cout << (dp[0][k][0] + dp[0][k][1]) % MOD << endl;
}
accuracy: 1
time_ms: 650
memory_kb: 503332
final_rank: 15

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

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define MT make_tuple
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second

#define DUMP(x) cout<<#x<<":"<<(x)<<endl
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class T>
istream& operator>>(istream& is, vector<T>& xs){
  for(auto& x: xs)
	is >> x;
  return is;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
ostream& operator<<(ostream& os, const vector<T>& xs){
  for(unsigned int i=0;i<xs.size();++i)
	os << (i?" ":"") << xs[i];
  return os;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}
void debug(istringstream&){}
template <char sep=',', class Head, class... Tail>
void debug(istringstream& iss, Head&& head, Tail&&... tail)
{
  string name;
  getline(iss, name, ',');
  cout << sep << name << "=" << head;
  debug(iss, forward<Tail>(tail)...);
}
#define DEBUG(...) \
  do{ \
    istringstream ss(#__VA_ARGS__); \
    debug<' '>(ss, __VA_ARGS__); \
    cout<<endl; \
  }while(0)


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 998244353;


const int MAXU = 100000 + 10;
const int MAXK = 300 + 10;
LL dp[2][MAXU][MAXK];
int sz[MAXU];

void add(LL& x, LL y){
    x += y;
    if(x >= MOD) x -= MOD;
}


LL solve(VVI& G, int K, int u, int p){
  sz[u] = 1;

  int ub = 2;
  VL nouse_crt(ub);
  VL use_crt(ub);
  nouse_crt[0] = 1;
  use_crt[1] = 1;

  for(int to : G[u]){
    if(to == p) continue;
    solve(G, K, to, u);

    int ksum = min(K, sz[u]);
    ub = min(K+10, ksum+sz[to]+2);
    VL nouse_nxt(ub);
    VL use_nxt(ub);

    for(int k1=0;k1<=ksum;++k1){
      for(int k2=0;k2<=sz[to] && k1+k2<=K+1;++k2){
        add(nouse_nxt[k1+k2], nouse_crt[k1] * dp[0][to][k2] % MOD);
        if(k2) add(nouse_nxt[k1+k2], nouse_crt[k1] * dp[1][to][k2] % MOD);

        add(use_nxt[k1+k2], use_crt[k1] * dp[0][to][k2] % MOD);
        if(k2) add(use_nxt[k1+k2-1], use_crt[k1] * dp[1][to][k2] % MOD);
        if(k2) add(use_nxt[k1+k2], use_crt[k1] * dp[1][to][k2] % MOD);
      }
    }
    
    sz[u] += sz[to];
    swap(nouse_crt, nouse_nxt);
    swap(use_crt, use_nxt);
  }

  REP(kk,ub){
    dp[0][u][kk] = nouse_crt[kk];
    dp[1][u][kk] = use_crt[kk];
  }

/*
  DEBUG(u);
  REP(i,2){
    cout << "use = " << i << endl;
    REP(kk,K+1){ cout << dp[i][u][kk] << " ";}
    cout << endl;
  }
  cout << "=================" << endl;
*/
  return (dp[0][u][K] + dp[1][u][K]) % MOD;
}


int main(){
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int N, K;
  cin >> N >> K;
  VVI G(N);
  REP(i,N-1){
    int u, v;
    cin >> u >> v;
    --u;
    --v;
    G[u].PB(v);
    G[v].PB(u);
  }

  cout << solve(G, K, 0, -1) << endl;

  return 0;
}
accuracy: 1
time_ms: 950
memory_kb: 507084
final_rank: 18