#include using namespace std; using ll = long long; const int MOD = 998244353; using Poly = vector; Poly poly_mul(const Poly& a, const Poly& b, int E) { Poly res(E + 1, 0); for (int i = 0; i <= E; i++) { for (int j = 0; j + i <= E; j++) { res[i + j] = (res[i + j] + (ll)a[i] * b[j]) % MOD; } } return res; } void poly_add_scaled(Poly& dst, const Poly& src, int scale, int E) { for (int i = 0; i <= E; i++) { dst[i] = (dst[i] + (ll)src[i] * scale) % MOD; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M, K; cin >> N >> M >> K; int E = N * (N - 1) / 2; int R = E - M; int S = N - 2; // binomial coefficients vector> C(E + 1, vector(E + 1, 0)); for (int i = 0; i <= E; i++) { C[i][0] = C[i][i] = 1; for (int j = 1; j < i; j++) { C[i][j] = C[i - 1][j - 1] + C[i - 1][j]; if (C[i][j] >= MOD) C[i][j] -= MOD; } } auto nCr = [&](int n, int r) -> int { if (r < 0 || r > n) return 0; return C[n][r]; }; // one_plus_pow[m] = (1+x)^m vector one_plus_pow(E + 1, Poly(E + 1, 0)); for (int m = 0; m <= E; m++) { for (int i = 0; i <= m; i++) { one_plus_pow[m][i] = C[m][i]; } } // trans[b][c] = // ((1+x)^b - 1)^c * (1+x)^{c(c-1)/2} vector> trans(N + 1, vector(N + 1, Poly(E + 1, 0))); for (int b = 0; b <= N; b++) { Poly base = one_plus_pow[b]; base[0]--; if (base[0] < 0) base[0] += MOD; Poly power(E + 1, 0); power[0] = 1; for (int c = 0; c <= N; c++) { if (c > 0) { power = poly_mul(power, base, E); } int inside_edges = c * (c - 1) / 2; trans[b][c] = poly_mul(power, one_plus_pow[inside_edges], E); } } // dp[a][b]: // a = number of ordinary vertices used in L_1,...,L_j // b = size of current BFS layer L_j vector> dp(S + 1, vector(N + 1, Poly(E + 1, 0))); // L_0 = {1} dp[0][1][0] = 1; for (int j = 0; j < K; j++) { vector> ndp(S + 1, vector(N + 1, Poly(E + 1, 0))); bool last = (j + 1 == K); for (int a = 0; a <= S; a++) { int rem = S - a; for (int b = 0; b <= N; b++) { if (!last) { // L_{j+1} contains only ordinary vertices. for (int c = 1; c <= rem; c++) { int ways = nCr(rem, c); int a2 = a + c; Poly tmp = poly_mul(dp[a][b], trans[b][c], E); poly_add_scaled(ndp[a2][c], tmp, ways, E); } } else { // L_K must contain vertex N. // If |L_K| = c, choose c-1 ordinary vertices. for (int c = 1; c <= rem + 1; c++) { int ways = nCr(rem, c - 1); int a2 = a + c - 1; Poly tmp = poly_mul(dp[a][b], trans[b][c], E); poly_add_scaled(ndp[a2][c], tmp, ways, E); } } } } dp.swap(ndp); } ll ans = 0; for (int a = 0; a <= S; a++) { int rem = S - a; for (int b = 0; b <= N; b++) { int free_edges = rem * b + rem * (rem - 1) / 2; Poly tmp = poly_mul(dp[a][b], one_plus_pow[free_edges], E); ans += tmp[R]; ans %= MOD; } } cout << ans << '\n'; return 0; }