Problem p00674 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <vector>
using namespace std;

// * XY座標
#define X real()
#define Y imag()

// * 点の表現
typedef complex<double> P;

// * 許容する誤差ε
const double EPS = 1e-10;
// * Infinity
const double INF = 1e12;
// * 円周率
const double PI = acos(-1.0);
// *
const P INF_P(INF, INF);

// * complex<double> の順序を定義する
namespace std {
bool operator<(const P &a, const P &b) {
  return (real(a) != real(b)) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

// * 点座標のデバッグ出力
void print(P p) {
  p.X += 200;
  p.Y += 200;
  cout << "point" << p << ";" << endl;
}

// * 2乗する
double sq(double x) { return x * x; }

// * 2点間の距離
double dist(P p1, P p2) { return abs(p1 - p2); }

// * 2つのスカラーが等しいかどうか
bool equal(double a, double b) { return (fabs(a - b) < EPS); }
// * 2つのベクトルが等しいかどうか
bool eq_v(P a, P b) { return (equal(a.X, b.X) && equal(a.Y, b.Y)); }

// ベクトル a の単位法線ベクトルを求める
vector<P> normal_unit(P a) {
  vector<P> vp;
  vp.push_back((a * P(0, 1)) / abs(a));
  vp.push_back((a * P(0, -1)) / abs(a));
  return vp;
}

// * 内積 (dot product) : a・b = |a||b|cosΘ
double dot(P a, P b) { return real(conj(a) * b); }

// * 外積 (cross product) : a×b = |a||b|sinΘ
double cross(P a, P b) { return imag(conj(a) * b); }

// CCW : 反時計回り (Counter Clock Wise)
// CW : 時計回り (Clock Wise)
enum { CCW = 1, CW = -1, ON = 0 };
// * 3点がどちら回りであるか返す, 3点が1直線に乗っているときは ON を返す
int ccw(const P &a, P b, P c) {
  b -= a, c -= a;
  double rotdir = cross(b, c);
  if (rotdir > EPS)
    return CCW;
  if (rotdir < -EPS)
    return CW;
  return ON;
}

// ラジアンから度数へ変換して返す
double to_deg(double rad) { return rad * 180.0 / PI; }

// 度数からラジアンに変換して返す
double to_rad(double deg) { return deg * PI / 180.0; }

// 原点を軸に点 p を角度 a (ラジアン)だけ回転させた点を返す
P rot(P p, double a) {
  double x = p.X * cos(a) - p.Y * sin(a);
  double y = p.X * sin(a) + p.Y * cos(a);
  return P(x, y);
}

// 点 a を軸に点 b を角度 a (ラジアン)だけ回転させた点を返す
P rot2(P a, P b, double angle) {
  P p = b - a;
  return rot(p, angle) + a;
}

// 線分の表現
struct Segment {
  // 点 a, b を端点とする線分
  P a, b;
  // コンストラクタで初期化
  Segment(P a_, P b_) {
    a = a_;
    b = b_;
  }
  // 線分の長さを返す
  double length() { return abs(a - b); }
  // 中点を返す
  P mid() { return P((a.X + b.X) / 2.0, (a.Y + b.Y) / 2.0); }
  // 点 p が線分上にあるかどうか
  bool contain(P p) { return (abs(a - p) + abs(p - b) < abs(a - b) + EPS); }
  // 線分と点 p の距離
  double distance(P p) {
    if (dot(b - a, p - a) < EPS)
      return abs(p - a);
    if (dot(a - b, p - b) < EPS)
      return abs(p - b);
    return abs(cross(b - a, p - a)) / abs(b - a);
  }
  // 線分の交差判定
  bool is_intersection(const Segment &s) {
    return (cross(b - a, s.a - a) * cross(b - a, s.b - a) < EPS) &&
           (cross(s.b - s.a, a - s.a) * cross(s.b - s.a, b - s.a) < EPS);
  }
  // 線分の交差判定と交点計算
  bool intersection(Segment s, P &p) {
    bool result = is_intersection(s);
    if (result) {
      double d1 = abs(cross(s.b - s.a, a - s.a));
      double d2 = abs(cross(s.b - s.a, b - s.a));

      if (abs(d1) < EPS && abs(d2) < EPS) { // 2つの線分が同じ直線上にあるとき
        if (this->contain(s.a)) {
          p = s.a;
        } else if (this->contain(s.b)) {
          p = s.b;
        } else if (s.contain(a)) {
          p = a;
        } else if (s.contain(b)) {
          p = b;
        } else {
          p = INF_P;
        }
      } else if (abs(d1) < EPS) {
        p = INF_P;
      } else {
        double t = d1 / (d1 + d2);
        p = a + (b - a) * t;
      }
    } else {
      p = INF_P;
    }
    return result;
  }
  // 線分と線分の距離
  double distance(Segment s) {
    if (this->is_intersection(s)) { // 交差するとき
      double d1 = abs(cross(s.b - s.a, a - s.a));
      double d2 = abs(cross(s.b - s.a, b - s.a));

      if (abs(d1) < EPS && abs(d2) < EPS) { // 2つの線分が同じ直線上にあるとき
        if (this->contain(s.a) || this->contain(s.b)) {
          return 0.0;
        } else if (s.contain(a) || s.contain(b)) {
          return 0.0;
        }
      } else {
        return 0.0;
      }
    }
    double A = this->distance(s.a);
    double B = this->distance(s.b);
    double C = s.distance((*this).a);
    double D = s.distance((*this).b);
    return min(min(A, B), min(C, D));
  }
  // 点 p を軸に 線分 を 角度 angle だけ回転移動 (角度はラジアン)
  Segment rot(P p, double angle) {
    P a_ = rot2(p, a, angle);
    P b_ = rot2(p, b, angle);
    return Segment(a_, b_);
  }
  // デバッグ出力
  void print() {
    printf("line(%f,%f,%f,%f); \\n", a.X + 200, a.Y + 200, b.X + 200, b.Y + 200);
  }
};
// Segment の順序を定義 (x座標の小さい端点で比較)
bool operator<(const Segment &s1, const Segment &s2) { return s1.a < s2.a; }

// 直線の表現 ((*this)[0]) と ((*this)[1]) を通る直線
struct Line : public vector<P> {
  Line(const P &a, const P &b) {
    push_back(a);
    push_back(b);
  }
  Line(vector<P> v) {
    push_back(v[0]);
    push_back(v[1]);
  }
  Line() {}
  // 2直線の直交判定
  bool orthogonal(const Line &l) {
    return equal(dot((*this)[0] - (*this)[1], l[0] - l[1]), 0.0);
  }
  // 2直線の平行判定
  bool parallel(const Line &l) {
    return equal(cross((*this)[0] - (*this)[1], l[0] - l[1]), 0.0);
  }
  // 点 p が直線上に乗っているか
  bool contain(P p) {
    return equal(cross((*this)[1] - (*this)[0], p - (*this)[0]), 0.0);
  }
  // 直線と点 p の距離
  double distance(P a) {
    P p1 = (*this)[0];
    P p2 = (*this)[1];
    return abs(cross(p2 - p1, a - p1)) / abs(p2 - p1);
  }
  // 直線の交差判定
  bool is_intersection(const Line &l) {
    return !equal(cross((*this)[0] - (*this)[1], l[0] - l[1]), 0.0);
  }
  // 直線の交差判定と交点計算
  bool intersection(Line l, P &p) {
    bool result = this->is_intersection(l);
    if (result) {
      P a = (*this)[1] - (*this)[0];
      P b = l[1] - l[0];
      p = (*this)[0] + a * cross(b, l[0] - (*this)[0]) / cross(b, a);
    } else {
      p = INF_P;
    }
    return result;
  }
  // 角度を返す [-π,π]
  double get_dir() {
    P p = (*this)[0] - (*this)[1];
    return atan2(p.Y, p.X);
  }
  // 双対変換
  P dual(const Line &l) {
    const P p = l[0], q = l[1];
    return P(imag(p - q) / real(p - q), cross(p, q) / real(q - p));
  }
  // 点を線対称に移動させる
  P symmetry(P a) {
    double x, y;
    double x1 = (*this)[0].X;
    double x2 = (*this)[1].X;
    double y1 = (*this)[0].Y;
    double y2 = (*this)[1].Y;
    double xq = a.X;
    double yq = a.Y;
    if (x2 == x1) {
      x = -xq;
      y = yq;
    } else {
      double m = (y2 - y1) / (x2 - x1);
      double c = y2 - m * x2;
      x = (2 * m * yq - xq * (m * m - 1) - 2 * m * c) / (m * m + 1);
      y = (2 * m * xq + yq * (m * m - 1) + 2 * c) / (m * m + 1);
    }
    return P(x, y);
  }
  // 点 p を軸に 直線 を 角度 angle だけ回転移動 (角度はラジアン)
  Line rot(P p, double angle) {
    P a = rot2(p, (*this)[0], angle);
    P b = rot2(p, (*this)[1], angle);
    return Line(a, b);
  }
  // デバッグ出力
  void print() {
    P p1 = (*this)[0];
    P p2 = (*this)[1];
    double dx = p1.X - p2.X;
    double dy = p1.Y - p2.Y;
    ::print(p1);
    ::print(p2);
    p1.X += 100 * dx;
    p1.Y += 100 * dy;
    p2.X -= 100 * dx;
    p2.Y -= 100 * dy;
    p1.X += 200;
    p1.Y += 200;
    p2.X += 200;
    p2.Y += 200;
    Segment s(p1, p2);
    s.print();
  }
};

// 三角形の表現
struct Triangle {
private:
  // 余弦定理から 3 つの角の角度を求める (内部の関数で使用)
  double law_of_cos(double a, double b, double c) {
    return acos((b * b + c * c - a * a) / (2.0 * b * c));
  }

public:
  // 3 つの頂点
  P a, b, c;
  // 3 つの辺の長さ
  double edgeA, edgeB, edgeC;
  // 3 つの角の角度 (ラジアン)
  double angleA, angleB, angleC;

  // コンストラクタで初期化
  Triangle(P p1, P p2, P p3) {
    a = p1;
    b = p2;
    c = p3;
    edgeB = abs(c - a);
    edgeA = abs(b - c);
    edgeC = abs(a - b);
    angleA = law_of_cos(edgeA, edgeB, edgeC);
    angleB = law_of_cos(edgeB, edgeC, edgeA);
    angleC = law_of_cos(edgeC, edgeA, edgeB);
  }
  // 三角形の面積を返す (ヘロンの公式)
  double get_area() {
    double s = 0.5 * (edgeA + edgeB + edgeC);
    return sqrt(s * (s - edgeA) * (s - edgeB) * (s - edgeC));
  }
  // 三角形の重心を返す
  P gravity() { return P((a.X + b.X + c.X) / 3.0, (a.Y + b.Y + c.Y) / 3.0); }
  // 点 p が三角形の辺上にあるかどうか
  bool on_boundary(P p) {
    Segment AB(a, b), BC(b, c), CA(c, a);
    return (AB.contain(p) || BC.contain(p) || CA.contain(p));
  }
  // 点 p が三角形の内部にあるかどうか ( AOJ 0012 で検証済み )
  // 点 p が三角形の辺上 or 頂点上
  // にあるときは誤差で正しい結果が返ってこないので注意!!!
  bool is_inside(P p) {
    // 辺上にあるとき
    if (this->on_boundary(p))
      return true;

    Triangle t1(a, b, p);
    Triangle t2(b, c, p);
    Triangle t3(c, a, p);
    // 角APB + 角BPB + 角CPA が 360度なら 点 p は三角形の内部にある
    return equal(t1.angleC + t2.angleC + t3.angleC, 2.0 * PI);
  }
  // 点 p を軸に 三角形 を 角度 angle だけ回転移動 (角度はラジアン)
  Triangle rot(P p, double angle) {
    P a_ = rot2(p, a, angle);
    P b_ = rot2(p, b, angle);
    P c_ = rot2(p, c, angle);
    return Triangle(a_, b_, c_);
  }
  // デバッグ出力
  void print() {
    Segment AB(a, b);
    Segment BC(b, c);
    Segment CA(c, a);
    AB.print();
    BC.print();
    CA.print();
  }
};

// 凸多角形かどうか (三角形に分割してすべての三角形が反時計回りか調べる)
bool is_convex(vector<P> g) {
  for (int i = 2; i < g.size(); i++) {
    if (ccw(g[0], g[i - 1], g[i]) != CCW)
      return false;
  }
  return true;
}

// 多角形の表現 (凸多角形と仮定する)
struct Polygon {
  // 頂点の集まり
  vector<P> g;
  // コンストラクタで初期化
  Polygon(vector<P> g_) { g = g_; }
  Polygon() {}
  // 点 p が凸多角形の内部にあるかどうか
  bool is_inside(P p) {
    for (int i = 2; i < g.size(); i++) {
      Triangle t(g[0], g[i - 1], g[i]);
      if (t.is_inside(p)) {
        return true;
      }
    }
    return false;
  }
  // 点 p が凸多角形の辺上にあるかどうか
  bool on_boundary(P p) {
    for (int i = 0; i < g.size(); i++) {
      Segment s(g[i], g[(i + 1) % g.size()]);
      if (s.contain(p))
        return true;
    }
    return false;
  }
  // 凸多角形の面積を返す
  double get_area() {
    double s = 0.0;
    for (int i = 2; i < g.size(); i++) {
      s += cross(g[i - 1] - g[0], g[i] - g[0]);
    }
    return s / 2.0;
  }
  // 凸多角形の重心を返す
  P gravity() {
    P sg(0, 0);
    double s = 0.0;
    for (int i = 2; i < g.size(); i++) {
      Triangle t(g[0], g[i - 1], g[i]);
      s += t.get_area();
      sg += t.get_area() * t.gravity();
    };
    return sg / s;
  }
  // 凸多角形の直径を返す (最遠点対は引数のpair<P,P> pに代入)
  double convex_diameter(pair<P, P> &p) {
    double result = 0.0;
    for (int i = 0; i < g.size(); i++) {
      for (int j = i + 1; j < g.size(); j++) {
        if (result < dist(g[i], g[j])) {
          result = dist(g[i], g[j]);
          p = pair<P, P>(g[i], g[j]);
        }
      }
    }
    return result;
  }
  // 凸多角形 を 直線l で切断し、直線の左側の多角形を返す
  Polygon convex_cut(Line l) {
    vector<P> Q;
    for (int i = 0; i < g.size(); i++) {
      P A = g[i];
      P B = g[(i + 1) % g.size()];
      if (ccw(l[0], l[1], A) != CW) {
        Q.push_back(A);
      }
      if (ccw(l[0], l[1], A) * ccw(l[0], l[1], B) < 0) {
        Line AB(A, B);
        P p;
        AB.intersection(l, p);
        Q.push_back(p);
      }
    }
    return Polygon(Q);
  }
  // 直線 s の方向( s.a から s.b へのベクトル ) と 最も遠い点を返す
  double d(int k, const Segment &s) { return dot(g[k], s.b - s.a); }
  P convex_extreme(const Segment &s) {
    int a = 0;
    int b = g.size();
    int n = g.size();
    if (d(0, s) >= d(n - 1, s) && d(0, s) >= d(1, s))
      return g[0];
    while (a < b) {
      int c = (a + b) / 2;
      if (d(c, s) >= d(c - 1, s) && d(c, s) >= d(c + 1, s))
        return g[c];
      if (d(a + 1, s) > d(a, s)) {
        if (d(c + 1, s) <= d(c, s) || d(a, s) > d(c, s))
          b = c;
        else
          a = c;
      } else {
        if (d(c + 1, s) > d(c, s) || d(a, s) >= d(c, s))
          a = c;
        else
          b = c;
      }
    }
  }
  // デバッグ用出力
  void print() {
    for (int i = 0; i < g.size(); i++) {
      Segment s(g[i], g[(i + 1) % g.size()]);
      s.print();
    }
  }
};

// 乱数の種の初期化 (最初に1回だけ呼び出す)
void init_rand() { srand((unsigned int)time(NULL)); }

// [a,b] の非負整数を返す。 (a,bは非負整数)
int random(int a, int b) {
  int range = b - a + 1;
  return rand() % range + a;
}

// [0,1] の浮動小数を返す
double random_2() { return (double)rand() / RAND_MAX; }

int main() {
  init_rand();

  int n;
  while (scanf("%d", &n), n) {
    vector<P> v;
    for (int i = 0; i < n; i++) {
      int x, y;
      scanf("%d %d", &x, &y);
      v.push_back(P(x, y));
    }
    Polygon G(v);
    double s = G.get_area();

    double low = PI * 0.5, high = PI * 1.5, mid = PI / 2;
    bool flag1 = false, flag2 = false;
    for (int i = 0; i < 100; i++) {
      if (flag1 && flag2)
        break;

      mid = random_2() * 2.0 * PI;
      Line l(P(0, 0), P(sin(mid), cos(mid)));
      double s1 = fabs(G.convex_cut(l).get_area());
      double s2 = s - s1;

      if (s1 - s2 > 0) {
        low = mid;
        flag1 = true;
      } else {
        high = mid;
        flag2 = true;
      }
    }
    while (low > high)
      high += 2 * PI;

    for (int i = 0; i < 100; i++) {
      mid = (low + high) / 2.0;
      Line l(P(0, 0), P(sin(mid), cos(mid)));
      double s1 = fabs(G.convex_cut(l).get_area());
      double s2 = s - s1;

      if (s1 - s2 > 0) {
        low = mid;
      } else {
        high = mid;
      }
    }
    {
      double x = sin(mid);
      double y = cos(mid);
      Line l(P(0, 0), P(x, y));
      Polygon G_ = G.convex_cut(l);
      // G_.print();
      double s1 = fabs(G_.get_area());
      double s2 = s - s1;
      // printf("// %.6f %.6f %.6f \\n", s, s1, s2 );
      printf("%.15f %.15f\\n", x, y);
    }
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <vector>
using namespace std;
// * XY座標
#define X real()
#define Y imag()

// * 点の表現
typedef complex<double> P;

// * 許容する誤差ε
const double EPS = 1e-10;
// * Infinity
const double INF = 1e12;
// * 円周率
const double PI = acos(-1.0);
// *
const P INF_P(INF, INF);

// * complex<double> の順序を定義する
namespace std {
bool operator<(const P &a, const P &b) {
  return (real(a) != real(b)) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

// * 点座標のデバッグ出力
void print(P p) { cout << "point" << p << ";" << endl; }

// * 2乗する
double sq(double x) { return x * x; }

// * 2点間の距離
double dist(P p1, P p2) { return abs(p1 - p2); }

// * 2つのスカラーが等しいかどうか
bool equal(double a, double b) { return (fabs(a - b) < EPS); }
// * 2つのベクトルが等しいかどうか
bool eq_v(P a, P b) { return (equal(a.X, b.X) && equal(a.Y, b.Y)); }

// * 内積 (dot product) : a・b = |a||b|cosΘ
double dot(P a, P b) { return real(conj(a) * b); }

// * 外積 (cross product) : a×b = |a||b|sinΘ
double cross(P a, P b) { return imag(conj(a) * b); }

// CCW : 反時計回り (Counter Clock Wise)
// CW : 時計回り (Clock Wise)
enum { CCW = 1, CW = -1, ON = 0 };
// * 3点がどちら回りであるか返す, 3点が1直線に乗っているときは ON を返す
int ccw(const P &a, P b, P c) {
  b -= a, c -= a;
  double rotdir = cross(b, c);
  if (rotdir > EPS)
    return CCW;
  if (rotdir < -EPS)
    return CW;
  return ON;
}

// ラジアンから度数へ変換して返す
double to_deg(double rad) { return rad * 180.0 / PI; }

// 度数からラジアンに変換して返す
double to_rad(double deg) { return deg * PI / 180.0; }

// 線分の表現
struct Segment {
  // 点 a, b を端点とする線分
  P a, b;
  // コンストラクタで初期化
  Segment(P a_, P b_) {
    if (b_ < a_)
      swap(a_, b_);
    a = a_;
    b = b_;
  }
  // 線分の長さを返す
  double length() { return abs(a - b); }
  // 中点を返す
  P mid() { return P((a.X + b.X) / 2.0, (a.Y + b.Y) / 2.0); }
  // 点 p が線分上にあるかどうか
  bool contain(P p) { return (abs(a - p) + abs(p - b) < abs(a - b) + EPS); }
  // 線分と点 p の距離
  double distance(P p) {
    if (dot(b - a, p - a) < EPS)
      return abs(p - a);
    if (dot(a - b, p - b) < EPS)
      return abs(p - b);
    return abs(cross(b - a, p - a)) / abs(b - a);
  }
  // 線分の交差判定
  bool is_intersection(const Segment &s) {
    return (cross(b - a, s.a - a) * cross(b - a, s.b - a) < EPS) &&
           (cross(s.b - s.a, a - s.a) * cross(s.b - s.a, b - s.a) < EPS);
  }
  // 線分の交差判定と交点計算
  bool intersection(Segment s, P &p) {
    bool result = is_intersection(s);
    if (result) {
      double d1 = abs(cross(s.b - s.a, a - s.a));
      double d2 = abs(cross(s.b - s.a, b - s.a));

      if (abs(d1) < EPS && abs(d2) < EPS) { // 2つの線分が同じ直線上にあるとき
        if (this->contain(s.a)) {
          p = s.a;
        } else if (this->contain(s.b)) {
          p = s.b;
        } else if (s.contain(a)) {
          p = a;
        } else if (s.contain(b)) {
          p = b;
        } else {
          p = INF_P;
        }
      } else if (abs(d1) < EPS) {
        p = INF_P;
      } else {
        double t = d1 / (d1 + d2);
        p = a + (b - a) * t;
      }
    } else {
      p = INF_P;
    }
    return result;
  }
};
// Segment の順序を定義 (x座標の小さい端点で比較)
bool operator<(const Segment &s1, const Segment &s2) { return s1.a < s2.a; }

// 三角形の表現
struct Triangle {
private:
  // 余弦定理から 3 つの角の角度を求める (内部の関数で使用)
  double law_of_cos(double a, double b, double c) {
    return acos((b * b + c * c - a * a) / (2.0 * b * c));
  }

public:
  // 3 つの頂点
  P a, b, c;
  // 3 つの辺の長さ
  double edgeA, edgeB, edgeC;
  // 3 つの角の角度 (ラジアン)
  double angleA, angleB, angleC;

  // コンストラクタで初期化
  Triangle(P p1, P p2, P p3) {
    a = p1;
    b = p2;
    c = p3;
    edgeB = abs(c - a);
    edgeA = abs(b - c);
    edgeC = abs(a - b);
    angleA = law_of_cos(edgeA, edgeB, edgeC);
    angleB = law_of_cos(edgeB, edgeC, edgeA);
    angleC = law_of_cos(edgeC, edgeA, edgeB);
  }
  // 三角形の面積を返す (ヘロンの公式)
  double get_area() {
    double s = 0.5 * (edgeA + edgeB + edgeC);
    return sqrt(s * (s - edgeA) * (s - edgeB) * (s - edgeC));
  }
  // 三角形の重心を返す
  P gravity() { return P((a.X + b.X + c.X) / 3.0, (a.Y + b.Y + c.Y) / 3.0); }
  // 点 p が三角形の辺上にあるかどうか
  bool on_boundary(P p) {
    Segment AB(a, b), BC(b, c), CA(c, a);
    return (AB.contain(p) || BC.contain(p) || CA.contain(p));
  }
  // 点 p が三角形の内部にあるかどうか ( AOJ 0012 で検証済み )
  // 点 p が三角形の辺上 or 頂点上
  // にあるときは誤差で正しい結果が返ってこないので注意!!!
  bool is_inside(P p) {
    // 辺上にあるとき
    if (this->on_boundary(p))
      return true;

    Triangle t1(a, b, p);
    Triangle t2(b, c, p);
    Triangle t3(c, a, p);
    // 角APB + 角BPB + 角CPA が 360度なら 点 p は三角形の内部にある
    return equal(t1.angleC + t2.angleC + t3.angleC, 2.0 * PI);
  }
};

// 凸多角形かどうか (三角形に分割してすべての三角形が反時計回りか調べる)
bool is_convex(vector<P> g) {
  for (int i = 2; i < g.size(); i++) {
    if (ccw(g[0], g[i - 1], g[i]) != CCW)
      return false;
  }
  return true;
}

// 多角形の表現 (凸多角形と仮定する)
struct Polygon {
  // 頂点の集まり
  vector<P> g;
  // コンストラクタで初期化
  Polygon(vector<P> g_) { g = g_; }
  Polygon() {}
  // 点 p が凸多角形の内部にあるかどうか
  bool is_inside(P p) {
    for (int i = 2; i < g.size(); i++) {
      Triangle t(g[0], g[i - 1], g[i]);
      if (t.is_inside(p)) {
        return true;
      }
    }
    return false;
  }
  // 点 p が凸多角形の辺上にあるかどうか
  bool on_boundary(P p) {
    for (int i = 0; i < g.size(); i++) {
      Segment s(g[i], g[(i + 1) % g.size()]);
      if (s.contain(p))
        return true;
    }
    return false;
  }
  // 凸多角形の面積を返す
  double get_area() {
    double s = 0.0;
    for (int i = 2; i < g.size(); i++) {
      s += cross(g[i - 1] - g[0], g[i] - g[0]);
    }
    return s / 2.0;
  }
  // 凸多角形の重心を返す
  P gravity() {
    P sg(0, 0);
    double s = 0.0;
    for (int i = 2; i < g.size(); i++) {
      Triangle t(g[0], g[i - 1], g[i]);
      s += t.get_area();
      sg += t.get_area() * t.gravity();
    };
    return sg / s;
  }
  // 凸多角形を 点 seg.a と 点 seg.b
  // を通る直線で切断し、直線の左側の多角形を返す
  Polygon convex_cut(const Segment &s) {
    vector<P> Q;
    for (int i = 0; i < g.size(); i++) {
      P A = g[i];
      P B = g[(i + 1) % g.size()];
      if (ccw(s.a, s.b, A) != CW) {
        Q.push_back(A);
      }
      if (ccw(s.a, s.b, A) * ccw(s.a, s.b, B) < 0) {
        Segment AB(A, B);
        P p;
        AB.intersection(s, p);
        Q.push_back(p);
      }
    }
    return Polygon(Q);
  }
  // 直線 s の方向( s.a から s.b へのベクトル ) と 最も遠い点を返す
  double d(int k, const Segment &s) { return dot(g[k], s.b - s.a); }
  P convex_extreme(const Segment &s) {
    int a = 0;
    int b = g.size();
    int n = g.size();
    if (d(0, s) >= d(n - 1, s) && d(0, s) >= d(1, s))
      return g[0];
    while (a < b) {
      int c = (a + b) / 2;
      if (d(c, s) >= d(c - 1, s) && d(c, s) >= d(c + 1, s))
        return g[c];
      if (d(a + 1, s) > d(a, s)) {
        if (d(c + 1, s) <= d(c, s) || d(a, s) > d(c, s))
          b = c;
        else
          a = c;
      } else {
        if (d(c + 1, s) > d(c, s) || d(a, s) >= d(c, s))
          a = c;
        else
          b = c;
      }
    }
  }
};

// 乱数の種の初期化 (最初に1回だけ呼び出す)
void init_rand() { srand((unsigned int)time(NULL)); }

// [a,b] の非負整数を返す。 (a,bは非負整数)
int random(int a, int b) {
  int range = b - a + 1;
  return rand() % range + a;
}

int main() {
  init_rand();

  int n;
  while (scanf("%d", &n), n) {
    vector<P> v;
    for (int i = 0; i < n; i++) {
      int x, y;
      scanf("%d %d", &x, &y);
      v.push_back(P(x, y));
    }
    Polygon G(v);
    double S = G.get_area();
    double dif_s;

    {
      P p = G.gravity();
      Segment seg(P(0, 0), p);
      Polygon G_ = G.convex_cut(seg);
      double s1 = G_.get_area();
      double s2 = S - s1;
      dif_s = s1 - s2;
      if (fabs(dif_s) < 1e-6) {
        printf("%.15f %.15f\\n", p.X, p.Y);
        continue;
      }
    }

    double angle1;
    while (true) {
      double angle = to_rad(random(0, 360));
      double x = 10.0 * sin(angle);
      double y = 10.0 * cos(angle);
      Segment s(P(0, 0), P(x, y));
      Polygon G_ = G.convex_cut(s);
      double s1 = G_.get_area();
      double s2 = S - s1;
      dif_s = s1 - s2;
      if (dif_s > EPS) {
        angle1 = angle;
        break;
      }
    }
    double angle2;
    while (true) {
      double angle = to_rad(random(0, 360));
      double x = 10.0 * sin(angle);
      double y = 10.0 * cos(angle);
      Segment s(P(0, 0), P(x, y));
      Polygon G_ = G.convex_cut(s);
      double s1 = G_.get_area();
      double s2 = S - s1;
      dif_s = s1 - s2;
      if (dif_s < EPS) {
        angle2 = angle;
        break;
      }
    }

    double ans_x, ans_y;
    while (true) {
      double angle = (angle1 + angle2) / 2.0;
      double x = 1.0 * sin(angle);
      double y = 1.0 * cos(angle);
      Segment s(P(0, 0), P(x, y));
      Polygon G_ = G.convex_cut(s);
      double s1 = G_.get_area();
      double s2 = S - s1;
      dif_s = s1 - s2;
      if (fabs(dif_s) < 1e-6) {
        ans_x = x;
        ans_y = y;
        break;
      }
    }
    printf("%.15f %.15f\\n", ans_x, ans_y);
  }
}