思路来自 某FXXL
不过复杂度咋算的..
/*
HDU 6091 - Rikka with Match [ 树形DP ] | 2017 Multi-University Training Contest 5
题意:给出N个点的树,求去边的方案数使得 去边后最大匹配数是M的倍数限制: N<=5e4, M<=200
分析:设 DP[u][i][0] 表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点没有匹配的方案数DP[u][i][1] 表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点匹配上的方案数得到对于 u 的某个子节点 v 对 u 的更新(讨论(u,v)的边连与不连)DP[u][k][0] += ∑ [i+j==k] 2 * DP[u][i][0] * DP[v][j][1] + 1 * DP[u][i][0] * DP[v][j][0]DP[u][k][1] += ∑ [i+j==k] 2 * DP[u][i][1] * ( DP[v][j][0] + DP[v][j][1] )DP[u][k][1] += ∑ [i+j==k-1] DP[u][i][0] * DP[v][j][0]每次在合并的时候更新u节点的取值范围,即 size[u] = min(size[u]+size[v], m) 这样复杂度大概 O(nm)(???)
*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL MOD = 998244353;
const int N = 5e4+5;
const int M = 205;
vector<int> G[N];
int t, n, m;
int size[N];
LL dp[N][M][2];
LL tmp[M<<1][2];
void solve(int u, int v)
{memset(tmp, 0, sizeof(tmp));for (int i = 0; i <= size[u]; i++)for (int j = 0; j <= size[v]; j++){tmp[i+j][1] += 2 * dp[u][i][1] * (dp[v][j][0]+dp[v][j][1]);tmp[i+j][1] %= MOD;tmp[i+j+1][1] += dp[u][i][0] * dp[v][j][0];tmp[i+j+1][1] %= MOD;tmp[i+j][0] += 2 * dp[u][i][0]*dp[v][j][1] + dp[u][i][0]*dp[v][j][0];tmp[i+j][0] %= MOD;}for (int i = 0; i < m; i++){dp[u][i][0] = (tmp[i][0] + tmp[i+m][0]) % MOD;dp[u][i][1] = (tmp[i][1] + tmp[i+m][1]) % MOD;}size[u] = min(m, size[u]+size[v]);
}
void dfs(int u, int pre)
{memset(dp[u], 0, sizeof(dp[u]));dp[u][0][0] = 1;size[u] = 1;for (auto & v : G[u]){if (v == pre) continue;dfs(v, u);solve(u, v);}
}
int main()
{scanf("%d", &t);while (t--){scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) G[i].clear();for (int i = 1; i < n; i++){int u, v; scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}dfs(1, 1);int ans = (dp[1][0][0]+dp[1][0][1]) % MOD;printf("%d\n", ans);}
}