あるエンジニアのAtCoder奮闘記

東京都港区にあるアミフィアブル株式会社のエンジニアが、AtCoderで解いた問題について振り返ったりしていく会社公認のブログです。

AtCoder AGC 036 A - Triangle (python)

irisruneです。Rustはきちんと勉強してから使わないと厳しい言語だと認識したので、しばらく温めることにします。

問題

atcoder.jp

あまりにも数学要素が強い問題ですが、アルゴリズム面でも少々癖があります(というか癖を出してしまいました)。

import sys
LIM = 1000000000


def input():
    return sys.stdin.readline().rstrip()


def main():
    s = int(input())

    x1 = 0 if s == LIM * LIM else 1
    y1 = 0
    x2 = min((s // LIM) + 1, LIM)
    y2 = s % LIM
    x3 = 0
    y3 = LIM
    print(x1, y1, x2, y2, x3, y3)


main()

何はともあれ三角形の面積を求める公式を使わないことには始まりません。座標点でもベクトルでも何でもいいので調べてきて、式変形を駆使してX_1=Y_1=0とおいたときに|X_2Y_3-Y_2X_3|=Sとなることを導き出しましょう。コンテスト当時の検索キーワードは間違いなく大変なことになっていたでしょう。

あとはこの式からX_2,Y_2,X_3,Y_3を求めるだけですが、ここも割と詰まりがちな部分だと思います。

自分が解いた道筋としては、はじめ2のべき乗を用いてビット演算で解こうとしていましたが、制約条件として0\leq X,Y\leq 10^9が設定されていたため、2^{30}=1073741824>10^9を扱うことができず解くことができませんでした。-10^9\leq X,Y\leq 10^9だと勘違いしていたんですね。

そこで、10^9で割ったときの商と剰余に分割して解こうとしましたが、絶対値の中身が和ではなく差であるため、無理やり和の形にしようとした結果上記コードのように少しややこしくなってしまいました。

具体的な方策としては、

  • S=10^{18}のとき、10^9で割った剰余は0となる。
    • そのため、X_1=X_3=0とおくことができる。
  • S\lt10^{18}のとき、10^9で割った商は10^9より小さくなる。
    • このとき、X'_2=X_2-1X_2を置き換えると、-1\leq X_2\leq 10^9-1である。
    • そのため、X_1=1とおくことでX'_3=-1X_3を置き換えることができる。
  • あとは10^9で割ったときの商と剰余をX_2,Y_2に、10^9Y_3に代入すればよい。

という形でした。商と剰余の和の形で計算することにこだわった結果、X_1=0という前提を崩したり3項演算子を用いたりと解説に困る形になってしまいましたね。

雑記

  • 今週(先週)はABCもAGCも問題が厳しめな気がします。
  • そろそろまたコンテストに参加したいですね。言語はGoの予定です。