問題
D – 阿弥陀
回答
ダブリング
ダブリングとは、 2倍することをlogN 回繰り返すことで Nに到達できることを利用する手法です。
あみだくじにはダブリングの手法が適用できます。
ちゃんと解くためには、「 冪乗法は結合法則を満たせば使用できる(群は定義より満たす) 」ということを理解していなければならないので、私にはまだ早い。
N, M, D = map(int, input().split())
A = list(map(int, input().split()))
amida = dict()
for i in range(N):
amida[i] = i
for a in reversed(A):
amida[a], amida[a-1] = amida[a-1], amida[a]
# D<=10**9 < 2 ** 30 なので、
# ダブリングを使うことで30通りの移動リスト考えるだけで良い。
k = D
move_list = [[int(i) for i in range(N)] for _ in range(30)]
for i in range(N):
move_list[0][i] = amida[i]
for k in range(1, 30):
for i in range(N):
move_list[k][i] = move_list[k-1][move_list[k-1][i]]
# ダブリングのため立っているビットの算出
k = 0
l = D
bin_index = []
while l > 0:
if l % 2 == 1:
bin_index.append(k)
k += 1
l //= 2
# ビットの立っている部分だけリストに従い移動
for i in range(N):
now = i
for k in bin_index:
now = move_list[k][now]
print(now + 1)