けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder AGC 036 A - Triangle (緑色, 400 点)

ちょっと面白い感じの構築問題!

問題概要

正の整数  S が与えられる。

以下の条件を満たす 3 つの格子点  (x_{1}, y_{1}), (x_{2}, y_{2}), (x_{3}, y_{3}) の組を一つ求めよ。

  • 座標値はすべて  0 以上  10^{9} 以下の整数値
  • 3 つの格子点からなる三角形の面積を 2 倍すると  S に一致

制約

  •  1 \le S \le 10^{18}

考えたこと

仮に 1 つの頂点を原点に固定することにすると、もう 2 つの座標を  (a, b), (c, d) としたとき、

 |ad - bc| = S

を満たすような整数  a, b, c, d を探す問題となる。ただし  S \le 10^{18} に対して、 0 \le a, b, c, d \le 10^{9} を満たさなければならない。

直感的には、 ad の値を大きくして、 bc の値を帳尻合わせに使えば良さそうだと思った。たとえば  S = 10^{18} であれば

  •  a = 1000000000, d = 1000000000
  •  b = 0, c = 0

とかで OK。 S = 987654321555555555 とかであれば、

  •  a = 1000000000, d = 987654322
  •  b = 1, c = 455555555

とかで OK。一般に、 S 10^{9} 以上の桁と、未満の桁とにわけてあげれば上手くいきそうだ。具体的には  p = 1000000000 として、

    long long a = (S + p - 1) / p;
    long long d = p;
    long long b = a * p - S;
    long long c = 1;

というふうにすればできた。 a S p で割って、小数点以下を切り上げた値となっている。

コード

#include <bits/stdc++.h>
using namespace std;

const long long p = 1000000000;
int main() {
    long long S;
    cin >> S;
    long long a = (S + p - 1) / p;
    long long d = p;
    long long b = a * p - S;
    long long c = 1;
    cout << "0 0 " << a << " " << b << " " << c << " " << d << endl;
}