//https://vjudge.csgrandeur.cn/contest/527767#problem/L
#include<bits/stdc++.h>
#include<unordered_map>
#include<array>
#define ll long long
#define ull unsigned long long
#define all(a) a.begin(),a.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-4;
const ll mod = 998244353;
const int N = 4e3 + 5;
#define int ll
int n, dp[N][N][2], fac[N], invfac[N], sz[N];
vector<int> g[N];
ll qpow(ll base, ll pow)
{
ll ans = 1;
while (pow)
{
if (pow & 1)
ans = ans * base % mod;
pow >>= 1;
base = base * base % mod;
}
return ans;
}
void init()
{
fac[0] = invfac[0] = 1;
for (int i = 1; i < N; i++)
{
fac[i] = fac[i - 1] * i % mod;
invfac[i] = qpow(fac[i], mod - 2);
}
}
ll C(int n, int m)
{
return fac[n] * invfac[m] % mod * invfac[n - m] % mod;
}
//for 枚举时,只枚举到sz,则dfs复杂度为 n ^ 2;
//for 枚举时,枚举到n,则dfs复杂度为 n ^ 3;
void dfs(int x, int fa)
{
dp[x][0][0] = 1;
sz[x] = 1;
for (auto to : g[x])
{
if (to == fa)
continue;
dfs(to, x);
for (int i = sz[x] / 2; i >= 0; i--)
{
for (int j = 0; j <= sz[to] / 2; j++)
{
if (j)
{
dp[x][i + j][0] += dp[x][i][0] * (dp[to][j][0] + dp[to][j][1]) % mod;
dp[x][i + j][1] += dp[x][i][1] * (dp[to][j][0] + dp[to][j][1]) % mod;
dp[x][i + j][0] %= mod;
dp[x][i + j][1] %= mod;
}
dp[x][i + j + 1][1] += dp[x][i][0] * dp[to][j][0] % mod;
dp[x][i + j + 1][1] %= mod;
}
}
sz[x] += sz[to];
}
}
void solve()
{
cin >> n;
for (int i = 1, u, v; i < 2 * n; i++)
{
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
init();
dfs(1, -1);
int ans = 0;
for (int i = 0; i <= n; i++)
{
int res_n = 2 * n - 2 * i;
int res_m = n - i;
int inv_rep = qpow(qpow(2, res_m), mod - 2);
ans += qpow(-1, i) * C(res_n, res_m) * fac[res_m] % mod * inv_rep % mod * (dp[1][i][0] + dp[1][i][1]) % mod + mod;
ans %= mod;
}
cout << ans << '\n';
}
signed main()
{
IOS;
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
L - Perfect Matchings (树形dp, 看上去复杂度为n^3,实际为n^2)
最新推荐文章于 2024-07-14 12:25:25 发布