Branched Evolution

Competitive Programming in Python

ABC 167 D - Teleporter

問題

$i=1,\ldots,n$ のそれぞれについて行き先 $A _ i$ が決まっているとき、$1$ を $k$ 回移動したときの行き先を求めよ。($n \leq 2 \times 10 ^ 5, \ k \leq 10 ^ {18}, 1 \leq A _ i \leq n$)

atcoder.jp

解説

$i$ を $2 ^ j $ 回移動したときの行き先を $DP[i][j]$ とすると、$2 ^ j $ 回の移動は$2 ^ {j-1} $ 回の移動を $2$ 回行うと考えて、 $$ DP[i][j] = DP[DP[i][j-1]][j-1] $$ が成り立つ。
$k$ 回の移動は $k$ を $2$ 進数展開して $$ k = 2 ^ {j _ 0} + \cdots + 2 ^ {j _ r} \ \ (j _ 0 < \cdots < j _ r) $$ と表してから、$j = j _ 0, \ldots,j _ r $ について $i$ を以下のように更新する。 $$ i \leftarrow DP[i][j] $$

実装

インデックスの都合で、補助的に $A _ 0 = 0$ とした。

n, k = map(int, input().split())
*A, = map(int, input().split())
A = [0] + A
bit = list(bin(k)[2:][::-1])
m = len(bit)
DP = [[None for j in range(m)] for i in range(n + 1)]
for i in range(n + 1):
    DP[i][0] = A[i]
for j in range(1, m):
    for i in range(n + 1):
        DP[i][j] = DP[DP[i][j - 1]][j - 1]
i = 1
for j, b in enumerate(bit):
    if b == '1':
        i = DP[i][j]
print(i)

atcoder.jp