結果
| 問題 |
No.1516 simple 門松列 problem Re:MASTER
|
| コンテスト | |
| ユーザー |
convexineq
|
| 提出日時 | 2021-05-21 23:11:01 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 109 ms / 6,000 ms |
| コード長 | 3,449 bytes |
| コンパイル時間 | 444 ms |
| コンパイル使用メモリ | 82,380 KB |
| 実行使用メモリ | 77,508 KB |
| 最終ジャッジ日時 | 2024-10-10 10:04:30 |
| 合計ジャッジ時間 | 3,164 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 19 |
ソースコード
def mul_poly(f,g):
df,dg = len(f),len(g)
res = [0]*(df+dg-1)
for i in range(df):
for j in range(dg):
res[i+j] += f[i]*g[j]
res[i+j] %= MOD
return res
def sub_poly(f,g):
df,dg = len(f),len(g)
m = max(df,dg)
res = f[:]+[0]*max(0,m-df)
for i in range(m):
if i < dg:
res[i] -= g[i]
if res[i] < 0: res[i] += MOD
return res
def divmod_poly(f,g):
assert g != [] and g != [0]
ginv = pow(g[-1],MOD-2,MOD)
df,dg = len(f),len(g)
if df < dg: return [0], f[:]
gg = [gi*ginv%MOD for gi in g]
r = f[:]
for i in range(df-dg,-1,-1):
for j in range(dg-2,-1,-1):
r[j+i] -= r[dg+i-1]*gg[j]
r[j+i] %= MOD
q = r[dg-1:]
r = r[:dg-1]
for i in range(df-dg+1): # g を monic にする
q[i] = q[i]*ginv%MOD
while r and r[-1]==0: r.pop()
if not r: r = [0]
return q,r
"""
数列 f の最小の線形漸化式を発見する
f = r/q (mod X^N) の形で返す
"""
def find_linear_reccurence(f):
r0 = [0]*len(f)+[1]
r1 = f[:]
while r1 and r1[-1]==0: r1.pop()
if not r1: return [0],[0] # all 0 なら 0 が解
q0,q1 = [0],[1]
r_ans, q_ans, size_ans = r1, q1, len(r1)+1
while r1 != [0]:
q,r = divmod_poly(r0,r1)
r0,r1 = r1,r
q0,q1 = q1,sub_poly(q0,mul_poly(q,q1))
size = max(len(q1),len(r1)+1)
if q1[0] and size < size_ans:
r_ans, q_ans, size_ans = r1, q1, size
if len(q_ans) <= len(r_ans):
q_ans += [0]*(len(r_ans)-len(q_ans)+1)
qinv = pow(q_ans[0],MOD-2,MOD)
for i in range(len(q_ans)): q_ans[i] = q_ans[i]*qinv%MOD
for i in range(len(r_ans)): r_ans[i] = r_ans[i]*qinv%MOD
return r_ans, q_ans
def polymul(f,g):
lf = len(f)
lg = len(g)
res = [0]*(lf+lg-1)
for i in range(lf):
for j in range(lg):
res[i+j] += f[i]*g[j]
res[i+j] %= MOD
return res
def fps_nth_term(f,g,N):
assert g[0] != 0
while N:
h = g[:]
for i in range(1,len(g),2):
h[i] = -h[i]
f = polymul(f,h)[N%2:N+1:2]
g = polymul(g,h)[:N+1:2]
N //= 2
return f[0]*pow(g[0],MOD-2,MOD)%MOD
n,k = map(int,input().split())
MOD = 998244353
dpn = [[0]*k for _ in range(k)]
dps = [[0]*k for _ in range(k)]
for i in range(k):
for j in range(i+1,k):
dpn[i][j] = dpn[j][i] = 1
dps[i][j] = dps[j][i] = i+j
M = 100
vn = [0]*M
vs = [0]*M
for I in range(M):
ndpn = [[0]*k for _ in range(k)]
ndps = [[0]*k for _ in range(k)]
for i in range(k):
for j in range(k):
if i<j:
for p in range(j):
if i==p: continue
ndpn[j][p] += dpn[i][j]
ndpn[j][p] %= MOD
ndps[j][p] += dps[i][j] + dpn[i][j]*p
ndps[j][p] %= MOD
elif i>j:
for p in range(j+1,k):
if i==p: continue
ndpn[j][p] += dpn[i][j]
ndpn[j][p] %= MOD
ndps[j][p] += dps[i][j] + dpn[i][j]*p
ndps[j][p] %= MOD
dpn = ndpn
dps = ndps
vn[I] = sum(sum(i) for i in dpn)%MOD
vs[I] = sum(sum(i) for i in dps)%MOD
r,q = find_linear_reccurence(vn)
print(fps_nth_term(r,q,n-3), end=" ")
r,q = find_linear_reccurence(vs)
print(fps_nth_term(r,q,n-3))
convexineq