ABC193E - Oversleepingの解説を書いてみます
コンテスト中に通せたので、自分の解法を書いてみます。
問題
概要
電車が秒で一方の街からもう一方の街に移動し、街に着いたときに秒停車する。高橋君は秒寝て秒起きるを繰り返す。高橋君は街で降車することができるか?もし可能ならば、最短何秒で降車できるか?ケースについて求めよ。
制約
厳密な問題の定義はもとの問題文を読んでください。
解法
状況整理
電車が街を出発してから、戻ってきて次に街を出発するまで秒かかります。つまり、電車の運動は周期秒の周期的な運動です。同様に、高橋君の睡眠に関する行動の周期は秒です。ところで、高橋君が街で電車を降りるためには、
- 電車が街に停車している間に高橋君が目を覚ます。
- 高橋君が起きている間に電車が街に到着する。
のいずれかが成立していれば良いです。そして、このいずれかが成り立つ最小の時刻が求める答えとなります。
周期的な運動であることから、電車の運動の状態は、時刻をで割った余りによって決まります。つまり、時刻をとすると、で表したときのによって電車の状態が決まります。一方、高橋君についても同じようにのによってのみ決まります。を消去して、の形にすることで、についての二元一次方程式が出来上がります。このそれぞれの時刻の表示を用いて、高橋君が街で電車を降りる条件を定式化してみると、
- かつ、つまり、方程式
- かつ、つまり、方程式
となります。それぞれの条件において、固定されていない方のおよびのとりうる範囲は高々なので、全ての場合について方程式を解いてみれば良いです。
商とあまりの定義
整数について、整数を用いて、と表します。をで割ったあまりとは、をこのような形で表したときのであって、となるような唯一の整数のことをいうものとします。また、をで割ったときの商とは、にをで割ったあまりをとったときののことを指すものとします。
以下に例を示します。
あまり | 商 | ||
---|---|---|---|
24 | 5 | 4 | 4 |
-24 | 5 | 1 | -5 |
24 | -5 | 4 | -4 |
-24 | -5 | 1 | 5 |
40 | -8 | 0 | -5 |
-13 | 26 | 13 | -1 |
-17 | 17 | 0 | -1 |
-11 | -5 | 4 | 3 |
拡張ユークリッドの互除法
いきなり一般的な問題を解くのは難しいと思うので、具体例を考えます。という方程式を解いてみましょう。後で示しますが、の係数(ここでは)の最大公約数が右辺の約数であるとき、またその時に限り、この形の方程式は整数解を持ちます。よって、この具体例では整数解が存在します。
2つの変数に対して方程式が1つなので、整数解は無数に存在します。たとえば、は解のひとつです。他にもも解のひとつです。このような解のひとつを機械的に求めるために、ユークリッドの互除法を使います。以下のように進んでいきます。
- あまりがになったので終了。
よって、最大公約数がであることが求まりますが、これらの各式をの形でみたときに、がどのように変化するかを行列表示で見てみたいと思います。
行列表示を知らない方もいると思うので必要なことだけ簡単に説明すると、行列とは要素を矩形に並べたもので、行列同士の積として
がなりたちます。また、2つの行列が等しいとは、両方の行列のサイズが等しく、かつ同じ場所にある要素が等しいことを意味します。
として、番目の式をと表します。ユークリッドの互除法のアルゴリズムのもっとも重要な事実として、との最大公約数はとと等しい、というものがあります。よって、です。このことを行列表示すると
となります。これは
のように書けるので、
とおきます。すると、
となります。この行列を求めることや計算していくことは、漸化式にしたがってその都度一つずつ順番に行えます。そして、初期値によらず最終的にはが、がの最大公約数になって終了するので、
となります。これの上側の要素を比較するとという式を得ます。このは元の方程式の解になっています。具体的には、
であるので、解が見つかりました。この解を利用することで、の解はこれを2倍したがみつかることもわかります。
また、をに変えるまでの最悪計算量は、がフィボナッチ数列の隣り合う項のときなのでです。
さらに、も方程式を満たすことがわかると思います。このことは一般に、に整数解が存在するなら、が以上未満になるように解を決めることが可能であることが言えます。そのように実装しておくと、解が存在しないときにを返すことで判定できるので便利です。
改めて、方程式の整数解を求める手順をまとめてみます。ここで、ををで割った商、ををで割ったあまりとします。
- とする。
- がならば手順4. へ。そうでなければ手順3. へ。
- とする。手順2. にもどる。
- この時点ではとの最大公約数になっている。もしがで割り切れなければ、を返し終了。
- とする。
- を倍する。
- も方程式の解としてとれる。とすると、となる。
- を返して終了。
本題
拡張ユークリッドの互除法で条件1. と条件2. を満たすを求めます。ただし、解が存在するならばどちらも以上でなくてはならないので、その条件も確かめる必要があります。は自動的にこの条件を満たします。が負になってしまう可能性があるように思えますが、それは起こらないことが示せます。
であったとすると、式変形により、条件1. では、条件2. ではですが、、であるので、自動的にが以上になることがわかります。
さらに、以上の方法で求めたは最小の非負整数解であるので、これで欲しいものは求まりました。あとは、解が存在するようなのもとでの最小値を求めれば良いです。
全体的な計算量はです。
コンテスト中のACコード
余談
解が存在しないときの出力が'infinity'
になっていることに気をつけましょう。僕はそれで2ペナ食らいました。