結果
| 問題 | No.3589 Make Ends Meet (Hard) |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-05-29 17:03:07 |
| 言語 | PyPy3 (7.3.17) |
| 結果 |
AC
|
| 実行時間 | 801 ms / 2,000 ms |
| コード長 | 3,231 bytes |
| 記録 | |
| コンパイル時間 | 227 ms |
| コンパイル使用メモリ | 95,852 KB |
| 実行使用メモリ | 272,264 KB |
| 最終ジャッジ日時 | 2026-07-10 20:55:38 |
| 合計ジャッジ時間 | 9,606 ms |
|
ジャッジサーバーID (参考情報) |
judge1_0 / judge3_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 47 |
ソースコード
MOD = 998244353
def modpow(a, e):
r = 1
while e > 0:
if e & 1:
r = r * a % MOD
a = a * a % MOD
e >>= 1
return r
def C(n, r):
if r < 0 or r > n:
return 0
return fact[n] * ifact[r] % MOD * ifact[n - r] % MOD
def mul_qs_minus_1_full(p, s, E):
res = [0] * (E + 1)
# p(q) * q^s
if s <= E:
for i in range(E + 1 - s):
res[i + s] = p[i]
# - p(q)
for i in range(E + 1):
res[i] -= p[i]
if res[i] < 0:
res[i] += MOD
return res
def add_shift_scaled_full(dst, src, shift, scale, E):
if scale == 0 or shift > E:
return
for i in range(E + 1 - shift):
if src[i] == 0:
continue
dst[i + shift] = (dst[i + shift] + src[i] * scale) % MOD
N, M, K = map(int, input().split())
E = N * (N - 1) // 2
R = E - M
S = N - 2
fact = [1] * (E + 1)
ifact = [1] * (E + 1)
for i in range(1, E + 1):
fact[i] = fact[i - 1] * i % MOD
ifact[E] = modpow(fact[E], MOD - 2)
for i in range(E, 0, -1):
ifact[i - 1] = ifact[i] * i % MOD
# dp[r][s] is a polynomial in q of fixed length E+1.
# r: number of ordinary vertices not reached yet
# s: size of current BFS frontier
dp = [[[0] * (E + 1) for _ in range(S + 2)] for _ in range(S + 1)]
active = [[False] * (S + 2) for _ in range(S + 1)]
dp[S][1][0] = 1
active[S][1] = True
# Build layers 1,2,...,K-1 without reaching vertex N.
for step in range(K - 1):
ndp = [[[0] * (E + 1) for _ in range(S + 2)] for _ in range(S + 1)]
nactive = [[False] * (S + 2) for _ in range(S + 1)]
for r in range(S + 1):
for s in range(S + 2):
if not active[r][s]:
continue
cur = dp[r][s][:] # cur * (q^s - 1)^t
for t in range(r + 1):
shift = t * (t - 1) // 2
ways = C(r, t)
add_shift_scaled_full(ndp[r - t][t], cur, shift, ways, E)
nactive[r - t][t] = True
if t != r:
cur = mul_qs_minus_1_full(cur, s, E)
dp = ndp
active = nactive
# H(q): generating polynomial for dist(1,N)=K in q=1+x.
H = [0] * (E + 1)
# N must have at least one edge to the current frontier: (q^s - 1).
# All edges among the remaining r ordinary vertices, between them and N,
# and between them and the current frontier are free.
for r in range(S + 1):
for s in range(S + 2):
if not active[r][s]:
continue
p = dp[r][s]
base = s * r + r + r * (r - 1) // 2
# p(q) * (q^s - 1) * q^base
for i in range(E + 1):
val = p[i]
if val == 0:
continue
# + p(q) * q^{base+s}
if i + base + s <= E:
H[i + base + s] += val
if H[i + base + s] >= MOD:
H[i + base + s] -= MOD
# - p(q) * q^base
if i + base <= E:
H[i + base] -= val
if H[i + base] < 0:
H[i + base] += MOD
# We need [x^R] H(1+x).
# If H(q)=sum_c h_c q^c, then
# [x^R] H(1+x) = sum_c h_c * C(c,R).
ans = 0
for c in range(R, E + 1):
ans += H[c] * C(c, R)
ans %= MOD
print(ans)