Open1
ABC367 D - Pedometer復習
問題設定
円形の場所に
各休憩所間の距離
休憩所sからtまで行くのにかかる最小の歩数はMの倍数
これを満たす休憩所の組
# (N: 休憩所の数, M: 割る数)
N, M = map(int, input().split())
# (A: 各休憩所間の距離)
A = list(map(int, input().split()))
# R配列の初期化 (累積歩数の余りを格納する配列)
# 0から2N-1までの累積歩数の余りを格納するためにサイズ2Nの配列を作る
R = [0] * (2 * N)
# 累積歩数の余りを計算して、R配列に格納する
for i in range(1, 2 * N):
# 前回の累積歩数の余りに次の休憩所までの距離を加えて M で割った余りを求める
R[i] = (R[i - 1] + A[(i - 1) % N]) % M
# B配列の初期化 (各余りが何回出現するかを記録する配列)
# Mで割った余りが0からM-1までの数値になるので、サイズMの配列を作る
B = [0] * M
# カウントを初期化 (条件を満たす (s, t) の組み合わせの数)
count = 0
# 最初のN個の余りについて、余りが何回出現するかを記録する
for i in range(N):
B[R[i]] += 1
# i=Nから2N-1までの範囲で余りを比較し、組み合わせを数える
for i in range(N, 2 * N):
# B[R[i - N]] を減算 (i - N の範囲を外す)
B[R[i - N]] -= 1
# 現在の R[i] と同じ余りが過去に出現している場合、その組み合わせをカウントに加える
count += B[R[i]]
# B[R[i]] を加算 (i の範囲に R[i] の余りを追加する)
B[R[i]] += 1
print(count)
フロー
-
R配列の計算:
-
R
配列は累積歩数の余りを保存します。2N個の要素を持つ配列を準備し、各休憩所の累積距離を ( M ) で割った余りを順に計算して格納します。
-
-
B配列の準備:
-
B
配列は各余りが何回出現したかを記録します。余りが ( 0 ) から ( M-1 ) までの範囲に収まるので、長さ ( M ) の配列を用意します。
-
-
条件を満たす組み合わせのカウント:
-
i = N
からi = 2N-1
までの間に、過去に同じ余りが出現していたかをチェックし、その場合は条件を満たす組み合わせとしてカウントに加えます。 - 各ループで、範囲から外れた過去の余りを
B
配列から除き、新しい余りをB
に追加します。
-