とした時、原点を通る直線によってできた2つの(境界を含まない)半平面のそれぞれに連続した添え字のベクトルが並んでいれば、に直交するベクトルが答えということになる。ただし、答えとなるベクトルは十分に原点に近い格子点を通る必要がある。
整数性の条件をいったん忘れると、直線を表すベクトルの候補は各から偏角を左右に微小にずらした通りが考えられる。そこで偏角順の尺取り法をして、それぞれのから偏角が以内におさまるすべてのの添え字を保持することにする。添え字がすべて連続している瞬間があればを回転したものを答えにすればよい。管理と判定はBITでできる。以下、実装のポイント:
- 尺取り法で区間を伸ばす場合の処理: ベクトルの候補とのクロス積がマイナスになるまで伸ばしていけばよい。[1]
- 尺取り法で区間を縮める場合の処理: とのクロス積がプラスになるまで縮めればよい。
- と同一か180度回転した偏角がに含まれる場合、(を回転したもの)は答えにできない。
さて、本の直線を用意する上で、整数性の条件を考慮しなくてはならない。単純化のために正数に限定して考える。ベクトルから反時計回りに微小に偏角を進めたベクトルを得ることは、であればファレイ数列においての直後にある分数を得ることと同じである。の場合も、逆数を取って直前の分数を得ると考えればよい。やり方を知らないのでググったらstackexchangeの質問が見つかった。ファレイ数列の隣接項はを満たすので、は互除法で求まるようだ。
クロス積がマイナスになるベクトルが存在しなかった場合はこれだとうまく処理できないように見える。こういうことが起こるのは、偏角ソートされたの隣接項同士がより開いている場合だが、問題設定より全ベクトルを足すとに戻るのでこの範囲に1つもベクトルがないということはありえない。 ↩︎