即看成两棵有根树分别处理,然后把大小为 k 的那个接到另一个的根上。而当 n 为偶数时,麻烦了,因为可能出现两个重心的情况,且其中一个还是根,即存在一棵子树大小恰等于 \frac{n}{2}。而现在还是有两种情况,第一种是这棵子树和去掉这棵子树后的原树(类比奇数情况下 f_k 和 f_{n-k})恰好同构,那这个就不会重复计数了,因为这俩根本质上是一样的。而其他情况就会重复计数一次,减掉的方案数即在所有可能的形态中选俩接起来:
#include <cstdio>
#include <algorithm>
const int N = 1e6 + 10, mod = 998244353; typedef long long ll;
int f[N], g[N], A[N], B[N], rev[N], lim, n, m;
inline int ksm(int a, int b)
{
int ret = 1;
while (b)
{
if (b & 1) ret = (ll)ret * a % mod;
a = (ll)a * a % mod; b >>= 1;
}
return ret;
}
inline void init(int n)
{
lim = 1; m = 0; while (lim <= n) lim <<= 1, ++m;
for (int i = 0; i < lim; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (m - 1));
}
inline void NTT(int* f, int len, int on)
{
for (int i = 0; i < len; ++i) if (i < rev[i]) std::swap(f[i], f[rev[i]]);
for (int h = 2; h <= len; h <<= 1)
{
int gn = ksm(3, (ll)on * ((mod - 1) / h) % (mod - 1));
for (int j = 0; j < len; j += h)
for (int k = j, g = 1; k < j + h / 2; ++k, g = (ll)g * gn % mod)
{
int u = f[k], t = (ll)g * f[k + h / 2] % mod;
f[k] = (u + t) % mod; f[k + h / 2] = ((u - t) % mod + mod) % mod;
}
}
if (on == mod - 2) for (int i = 0, inv = ksm(len, on); i < len; ++i) f[i] = (ll)f[i] * inv % mod;
}
inline void mul(int* f, int lF, int* g, int lG)
{
for (int i = 0; i < lF; ++i) A[i] = f[i];
for (int i = lF; i < lim; ++i) A[i] = 0;
for (int i = 0; i < lG; ++i) B[i] = g[i];
for (int i = lG; i < lim; ++i) B[i] = 0;
NTT(A, lim, 1); NTT(B, lim, 1);
for (int i = 0; i < lim; ++i) A[i] = (ll)A[i] * B[i] % mod;
NTT(A, lim, mod - 2);
}
inline void cdq(int l, int r)
{
if (r == 1) return ;
if (l + 1 == r)
{
if (l != 1) f[l] = (ll)f[l] * ksm(l - 1, mod - 2) % mod;
for (int i = l; i < n; i += l) (g[i] += (ll)f[l] * l % mod) %= mod;
return ;
}
int mid = (l + r) >> 1; cdq(l, mid); init(r - l);
if (l > 0)
{
mul(f, r - l, g + l, mid - l);
for (int i = mid; i < r; ++i) (f[i] += A[i - l]) %= mod;
}
mul(f + l, mid - l, g, !l ? mid : r - l);
for (int i = mid; i < r; ++i) (f[i] += A[i - l]) %= mod;
cdq(mid, r);
}
signed main()
{
int m; scanf("%d", &m); n = 1; while (n <= m) n <<= 1;
f[1] = 1; cdq(0, n); int ans = f[m];
for (int i = m / 2 + 1; i < m; ++i) (ans += (ll)(mod - f[i]) * f[m - i] % mod) %= mod;
if (!(m & 1)) (ans += (mod - (ll)f[m / 2] * (f[m / 2] - 1) / 2 % mod)) %= mod;
printf("%d\n", ans); return 0;
}