結果
| 問題 | No.3589 Make Ends Meet (Hard) |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-06-13 16:40:34 |
| 言語 | PyPy3 (7.3.17) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 3,594 bytes |
| 記録 | |
| コンパイル時間 | 237 ms |
| コンパイル使用メモリ | 96,100 KB |
| 実行使用メモリ | 101,412 KB |
| 最終ジャッジ日時 | 2026-07-10 21:02:12 |
| 合計ジャッジ時間 | 4,441 ms |
|
ジャッジサーバーID (参考情報) |
judge1_0 / judge2_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 TLE * 1 |
| other | -- * 47 |
ソースコード
import sys
def solve():
input_data = sys.stdin.read().split()
if not input_data:
return
N = int(input_data[0])
M = int(input_data[1])
K = int(input_data[2])
MOD = 998244353
total_edges = N * (N - 1) // 2
rem_edges = total_edges - M
if rem_edges < 0:
print(0)
return
MAX_C = max(total_edges + 1, N + 1)
C = [[0] * MAX_C for _ in range(MAX_C)]
for i in range(MAX_C):
C[i][0] = 1
for j in range(1, i + 1):
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD
# 状態: curr_states[(prev_sz, u, e)]
# prev_sz: 直前の層の頂点数, u: 配置済みの自由頂点数, e: 確定した「残した辺」の数
curr_states = {(1, 0, 0): 1}
for d in range(1, K + 1):
next_states = {}
for (prev_sz, u, e), ways in curr_states.items():
rem_v = (N - 2) - u
min_vars = 0
max_vars = rem_v
if d != K:
min_vars = max(min_vars, 1)
for k_vars in range(min_vars, max_vars + 1):
sz = k_vars + (1 if d == K else 0)
if sz == 0:
continue
v_choices = C[rem_v][k_vars]
if v_choices == 0:
continue
# 直前の層(prev_sz)との接続の組合せ(各頂点1本以上)
ways_to_connect = [0] * (prev_sz + 1)
for j in range(1, prev_sz + 1):
ways_to_connect[j] = C[prev_sz][j]
sz_conn = [0] * (prev_sz * sz + 1)
sz_conn[0] = 1
for _ in range(sz):
next_sz_conn = [0] * (len(sz_conn))
for e1 in range(len(sz_conn)):
if sz_conn[e1] == 0:
continue
for e2 in range(1, prev_sz + 1):
if e1 + e2 < len(next_sz_conn):
next_sz_conn[e1 + e2] = (
next_sz_conn[e1 + e2]
+ sz_conn[e1] * ways_to_connect[e2]
) % MOD
sz_conn = next_sz_conn
# 同一層内の辺
inner_max = sz * (sz - 1) // 2
ways_inner = [C[inner_max][i] for i in range(inner_max + 1)]
base_ways = (ways * v_choices) % MOD
for e_conn, w_conn in enumerate(sz_conn):
if w_conn == 0:
continue
for e_inner, w_inner in enumerate(ways_inner):
added_edges = e_conn + e_inner
if e + added_edges > rem_edges:
continue
n_u = u + k_vars
n_e = e + added_edges
n_ways = (base_ways * w_conn % MOD) * w_inner % MOD
state_key = (sz, n_u, n_e)
next_states[state_key] = (
next_states.get(state_key, 0) + n_ways
) % MOD
curr_states = next_states
ans = 0
for (prev_sz, u, e), ways in curr_states.items():
rem_v_final = (N - 2) - u
free_edges = (
rem_v_final * (rem_v_final - 1) // 2 + prev_sz * rem_v_final
)
needed = rem_edges - e
if 0 <= needed <= free_edges:
ans = (ans + ways * C[free_edges][needed]) % MOD
print(ans)
if __name__ == "__main__":
solve()