あらすじ
問題を解いたのですが公式解説に書かれていた知識を持っておらず、回り道をしていたので思考過程のメモをしました。
なお該当のコンテストには出ておらず、「線形変換」というキーワードは目にした状態でスタートしていました。
問題概要
二次元平面上に個の駒
が置かれている。
以下のうち一つを行う、という操作が合計回行われる。
- 平面全体を時計回りに90度回転
- 平面全体を反時計回りに90度回転
- すべての駒を
に対して対称な位置に移動
- すべての駒を
に対して対称な位置に移動
個のクエリに答える。
回目の操作が行われた直後に
番目の駒はどこにあるか。
解法概要
各クエリに対してシミュレーションをすると間に合わない。
4つの操作は全て平面に対する線形変換なので、変換行列の積を取ることで複数回の連続する操作をまとめて1度の変換で行うことができる。
公式解説
Editorial - AtCoder Beginner Contest 189 を見てください
4つの操作はそれぞれ、
座標を表すベクトル に対して
(追記)
上の変換行列の導出を教えてもらいました。
同時座標系という手法を用いることで平行移動を(ベクトルではなく)行列で表現することができ、以下に書かれているのと同じような平行移動->対称移動->平行移動の操作を一つの行列にまとめることができる、という話でした。
自分の考察
※まず変換行列は2×2だと思っている
それぞれの変換が行列で表せれば累積積で各クエリに対して で対処できる
回転行列はわかるが、鏡写しの場合が分からない(ググったが雑過ぎて引っかからず)
ではなくy軸対称の変換なら
で表せて嬉しい。
なので、一度平行移動により対称移動の軸がy軸と重なるようにして、上記行列を作用させた後に平行移動を元に戻す。
例: (2, -1) を x=3に対して対称な位置へ
左右対称移動について一般化
として、移動後の座標をとすると
変換前の座標に依存しない部分をと定義して、
複数回の変換
y = p_1 を軸とした対称変換の後に y = p_2を軸とした対称変換をするとどうなるか
とする。(後々の一般化のために、A_1とA_2は別物としている)
で結局、初期値を
とすると、 回目までのすべての変換による結果を表す行列およびベクトルは
の漸化式で表せる。
実装上は累積積(のようなもの)を保持する配列を2つ用意して末尾に逐次pushしていけばいいので、
4つの操作に対する一般化
前節までは左右対称の変化のみを扱っていたが、他の操作に対しても
と定義することでそのまま使うことができる。
前述のとおりACすることができる。
解答
Submission #19659845 - AtCoder Beginner Contest 189
(累積積を持っているということは、時刻での変換を切り取るとかもできそうですが、逆行列がなかったりする場合もあるのかな)
免責
数学の議論とはてなブログの記法に疎いため、数式のふりをしたただのお気持ち表明が多くなっています、すみません。