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{元の前面})\)、新しい前面は元の上面となります。

サイコロ同士は互いに影響を与えないため、他のサイコロの位置を気にする必要はありません。

アルゴリズム

  1. 各サイコロの現在の位置、上面の数、前面の数を管理するための配列(リスト)を長さ \(N+1\) で用意し、初期状態で埋めます。
  2. \(Q\) 回の操作を順に読み込み、指定されたサイコロ \(d\) に対して以下の更新を行います。
    • 方向が + の場合:位置を \(+1\) し、上面と前面の数を (新しい上面, 新しい前面) = (元の前面, 7 - 元の上面) に更新します。
    • 方向が - の場合:位置を \(-1\) し、上面と前面の数を (新しい上面, 新しい前面) = (7 - 元の前面, 元の上面) に更新します。
  3. すべての操作が終了した後、各サイコロの最終的な位置と上面の数を出力します。

計算量

  • 時間計算量: \(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 によって生成されました。