Official
A - サイコロの転がし操作 / Dice Rolling Operations Editorial by admin
gemini-3.1-pro-thinking概要
\(N\) 個のサイコロに対して \(Q\) 回の転がす操作が与えられるので、問題文のルールに従って各サイコロの位置と姿勢をシミュレーションし、最終的な状態を求める問題です。
考察
制約を確認すると、サイコロの個数 \(N\) と操作回数 \(Q\) はともに最大 \(10^5\) です。各操作では \(1\) つのサイコロの位置と姿勢を更新するだけなので、\(1\) 回の操作は \(O(1)\) で処理できます。したがって、すべての操作を順番にそのままシミュレーションしても、全体で \(O(Q)\) となり実行時間制限に十分に間に合います。
サイコロの姿勢は「上面」と「前面」の \(2\) つの値で管理できます。問題文には転がしたときの変化のルールが丁寧に記述されているため、これに忠実に状態を更新していけばよいです。
+方向に転がす場合:新しい上面は元の前面、新しい前面は \(7 - (\text{元の上面})\) となります。-方向に転がす場合:新しい上面は \(7 - (\text{元の前面})\)、新しい前面は元の上面となります。
サイコロ同士は互いに影響を与えないため、他のサイコロの位置を気にする必要はありません。
アルゴリズム
- 各サイコロの現在の位置、上面の数、前面の数を管理するための配列(リスト)を長さ \(N+1\) で用意し、初期状態で埋めます。
- \(Q\) 回の操作を順に読み込み、指定されたサイコロ \(d\) に対して以下の更新を行います。
- 方向が
+の場合:位置を \(+1\) し、上面と前面の数を(新しい上面, 新しい前面) = (元の前面, 7 - 元の上面)に更新します。 - 方向が
-の場合:位置を \(-1\) し、上面と前面の数を(新しい上面, 新しい前面) = (7 - 元の前面, 元の上面)に更新します。
- 方向が
- すべての操作が終了した後、各サイコロの最終的な位置と上面の数を出力します。
計算量
- 時間計算量: \(O(N + Q)\)
- 初期状態の読み込みに \(O(N)\)、シミュレーションに \(O(Q)\)、結果の出力に \(O(N)\) かかります。
- 空間計算量: \(O(N + Q)\)
- サイコロの状態を保持する配列に \(O(N)\) のメモリを使用します。また、高速化のために入力全体を一括で読み込む場合は \(O(N + Q)\) のメモリを消費します。
実装のポイント
多重代入の活用 Pythonでは
a, b = c, dのような多重代入を使うことで、古い値を一時変数(tempなど)に退避させることなく、上面と前面の更新を \(1\) 行で安全かつ簡潔に記述できます。高速な入出力 入力行数が最大で \(2 \times 10^5\) 行程度になるため、標準の
input()やprint()を毎行呼び出すと実行時間が長くなる(TLEになる)可能性があります。sys.stdin.read().split()で入力を一括で読み込み、出力もリストにまとめてから'\n'.join()で一気に出力することで、大幅に高速化できます。ソースコード
import sys
def main():
input_data = sys.stdin.read().split()
if not input_data:
return
N = int(input_data[0])
M = int(input_data[1])
Q = int(input_data[2])
pos = [0] * (N + 1)
U = [0] * (N + 1)
F = [0] * (N + 1)
idx = 3
for i in range(1, N + 1):
pos[i] = int(input_data[idx])
U[i] = int(input_data[idx+1])
F[i] = int(input_data[idx+2])
idx += 3
for _ in range(Q):
d = int(input_data[idx])
c = input_data[idx+1]
idx += 2
if c == '+':
pos[d] += 1
U[d], F[d] = F[d], 7 - U[d]
else:
pos[d] -= 1
U[d], F[d] = 7 - F[d], U[d]
out = []
for i in range(1, N + 1):
out.append(f"{pos[i]} {U[i]}")
print('\n'.join(out))
if __name__ == '__main__':
main()
この解説は gemini-3.1-pro-thinking によって生成されました。