結果
問題 | No.2310 [Cherry 5th Tune A] Against Regret |
ユーザー | navel_tos |
提出日時 | 2023-05-20 19:07:04 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 2,984 ms / 6,000 ms |
コード長 | 3,047 bytes |
コンパイル時間 | 1,523 ms |
コンパイル使用メモリ | 85,620 KB |
実行使用メモリ | 90,952 KB |
最終ジャッジ日時 | 2023-08-23 09:48:53 |
合計ジャッジ時間 | 44,570 ms |
ジャッジサーバーID (参考情報) |
judge13 / judge11 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 71 ms
70,768 KB |
testcase_01 | AC | 68 ms
70,992 KB |
testcase_02 | AC | 75 ms
71,364 KB |
testcase_03 | AC | 117 ms
77,612 KB |
testcase_04 | AC | 94 ms
76,676 KB |
testcase_05 | AC | 101 ms
77,280 KB |
testcase_06 | AC | 108 ms
77,564 KB |
testcase_07 | AC | 97 ms
77,084 KB |
testcase_08 | AC | 390 ms
81,732 KB |
testcase_09 | AC | 563 ms
81,032 KB |
testcase_10 | AC | 711 ms
81,984 KB |
testcase_11 | AC | 909 ms
81,744 KB |
testcase_12 | AC | 974 ms
82,424 KB |
testcase_13 | AC | 513 ms
80,484 KB |
testcase_14 | AC | 600 ms
79,924 KB |
testcase_15 | AC | 1,021 ms
81,784 KB |
testcase_16 | AC | 228 ms
78,692 KB |
testcase_17 | AC | 601 ms
80,536 KB |
testcase_18 | AC | 2,943 ms
90,576 KB |
testcase_19 | AC | 2,958 ms
90,444 KB |
testcase_20 | AC | 2,944 ms
90,952 KB |
testcase_21 | AC | 2,965 ms
90,780 KB |
testcase_22 | AC | 2,924 ms
90,856 KB |
testcase_23 | AC | 2,960 ms
90,752 KB |
testcase_24 | AC | 2,934 ms
90,368 KB |
testcase_25 | AC | 2,950 ms
90,708 KB |
testcase_26 | AC | 2,949 ms
90,500 KB |
testcase_27 | AC | 2,967 ms
90,532 KB |
testcase_28 | AC | 2,984 ms
90,744 KB |
testcase_29 | AC | 633 ms
81,216 KB |
ソースコード
#yukicoder389F Against Regret ''' なんだか解けそう。 頂点iから頂点jへの移動経路として考えられるものの総数を前計算する。 DAGであることを利用すれば、ゴール側から順に計算してゆくことでO(N^3)に収まる。 事前に追加した辺集合を「下道での移動」と呼称する。 各クエリで追加する辺集合を「高速道路での移動」と呼称しよう。 頂点0から頂点Nへのパスとして考えられるものは ・下道だけで0→Nに移動する ・下道で0→i、高速でi→j、下道でj→N ・下道で0→i、高速でi→j、下道でj→k、高速にまた乗ってk→L、下道でL→N ・高速に一時的に乗って、下道に降りて1区間以上進んで、・・・ となる。 なので、高速道路の各地点において ・今高速道路を降りて、下道で次の高速道路の地点かゴールに向かう。 ・今高速道路に乗る。 とする場合の数を管理すればよい。 あとは 下道だけで0→Nの移動をする場合の数と足せばよい。 ''' import sys; input=sys.stdin.readline f=lambda:list(map(int,input().split())) N=int(input()); X=[f() for _ in range(N+1)]; MOD=998244353 #local[i][j]: iからjに移動を行う場合の数 local=[[0]*(N+1) for _ in range(N+1)] for i in range(N,-1,-1): for j in range(i+1,N+1): for k in range(i+1,j): #kを経由する場合 local[i][j]+=X[i][k]*local[k][j]; local[i][j]%=MOD local[i][j]+=X[i][j]; local[i][j]%=MOD #直接iからjに移動する場合の数 #クエリに回答。高速道路の頂点名は0~Nではなく、座圧したもので呼ぶので注意 for _ in range(int(input())): K=int(input()); Task=[f() for _ in range(K)] R=sorted(set([Task[x][y] for x in range(K) for y in [0,1]])) D={j:i for i,j in enumerate(R)} #G[x][y]: 座圧した頂点xからyに移動する、追加した有向辺の本数 G=[[0]*len(D) for _ in range(len(R))] for a,b,c in Task: G[D[a]][D[b]]+=c #highway[x][t]: 座圧した頂点xに対して、辺状態がtの辺を最後に使ってxに到達する場合の数 #t=0: 1回以上追加した有向辺を使ったうえで、既存の辺を最後に使ってxに到達 #t=1: 追加した有向辺を最後に使ってxに到達 highway=[[0]*2 for _ in range(len(R))] #初期化するが、頂点0と頂点Nだけは特別扱いする。 ans=local[0][N]; local[0][0]=local[N][N]=1 for x,i in enumerate(R): #1. 一度高速を降りて別の頂点に向かうケース for y in range(x+1,len(R)): highway[y][0]+=highway[x][1]*local[i][R[y]]%MOD; highway[y][0]%=MOD ans+=highway[x][1]*local[i][N]%MOD; ans%=MOD #2. ここから高速に乗って別の頂点に遷移するケース for y in range(x+1,len(R)): highway[y][1]+=(local[0][i]+highway[x][0]+highway[x][1])*G[x][y]%MOD highway[y][1]%=MOD print(ans%MOD)