Easyで誤読&実装方針をミス、解けたと思ったMedはシステムテストで落ちて0完。青に落ちてしまった。
OlympicShooting
これは読解&実装問題。
・スコアの合計が高い方が勝ち
・同じなら、後ろから順に、25回ずつのスコアが高い方が勝ち。
・それも同じなら、より後でスコア獲得した方が勝ち。
というのを実装する。
最初、「25回ずつ」というのを読み飛ばして戸惑った。
その後、上手い実装がないかと考えていたのが失敗(とはいえ、短くコードをまとめている人もいた)。多少時間がかかっても愚直に書けば良かった。
TreeTokens
解法はすぐに分かり、それであっていたが実装でミスしてしまった。
ROOTに駒がこないためには、ROOTの隣は1個しかあってはダメ。じゃあ、その隣は、というと、3個までしかあってはダメ。その隣は7個まで。さらにその隣は15個まで。
つまり、ある頂点の駒が高々i個になるためには、その隣の頂点での駒は高々2*i+1個であれば良い。問題が直線状で、ROOTが端にあれば、N=(頂点数-1)として、2^N-1個が答えになる。
では分岐があったときは? というと、葉が深い方の枝に駒を増やしていく(2*i+1倍していく)のが最善。もう一つの分岐は、駒1個からまた増やしていく。
そういう感じで、各頂点について「葉までの距離のmax」を前計算した後、ROOTの方がから木DPをしていく感じに解いた。
……のだが、「葉までの距離のmax」の前計算する箇所で間違えた。
これはよくある木DPなので、トポロジカルソートの逆順に見ていけば良いのだが、なぜかDFSみたいにしてしまっていた。
焦っていたとはいえ良くない間違いでした。
システムテストを通ったコードです。
mod=1000000007
class TreeTokens ():
def placeMax(self, N, G, L, seed):
state = seed
E=[[] for i in range(N)]
for i in range(1,N):
state = (state * 1103515245 + 12345) % (1<<31)
tmp = (state // 1000) % L
p = max(0, i-1-tmp)
E[i].append(p)
E[p].append(i)
#print(E)
ROOT=G
QUE=[ROOT]
Parent=[-1]*(N+1)
Parent[ROOT]=N # ROOTの親を定めておく.
TOP_SORT=[] # トポロジカルソート
while QUE: # トポロジカルソートと同時に親を見つける
x=QUE.pop()
TOP_SORT.append(x)
for to in E[x]:
if Parent[to]==-1:
Parent[to]=x
QUE.append(to)
CC=[-1]*N
for x in TOP_SORT[::-1][:-1]:
if CC[x]==-1:
CC[x]=1
if Parent[x]==ROOT:
continue
CC[Parent[x]]=max(CC[Parent[x]],CC[x]+1)
AC=[0]*N
AC[ROOT]=0
ANS=0
QUE=[ROOT]
while QUE:
x=QUE.pop()
MAX=-1
if len(E[x])==1 and x!=ROOT:
ANS+=AC[x]
ANS%=mod
for to in E[x]:
if to==Parent[x]:
continue
MAX=max(CC[to],MAX)
USE=0
for to in E[x]:
if to==Parent[x]:
continue
if CC[to]==MAX and USE==0:
USE=1
AC[to]=(AC[x]*2+1)%mod
else:
AC[to]=1
QUE.append(to)
return ANS%mod