// https://szkopul.edu.pl/problemset/problem/oFbVh8iOGlqNYUUueTt5V9N4/site/?key=statement
#include <bits/stdc++.h>
// using namespace std;
// #define GARY_DBG
#define GARY_LIB
#define int long long
constexpr int sizik = 3001;
#define ar std::array
#define pr std::pair
#define vec std::vector
typedef vec<vec<int>> _kra;
namespace brut {
std::pair<int, int> points[sizik];
void solve(int n);
}
struct Point {
int x, y;
int id;
Point(int x1, int y1, int id1) : x(x1), y(y1), id(id1) {}
Point(int x1, int y1) : x(x1), y(y1), id(0) {}
Point() { *this = Point(0, 0, 0); }
// Point(int x1, int y1, int id1) : x(x1), y(y1), id(id1) {}
Point operator+(const Point& other) const { return Point(x + other.x, y + other.y, id); }
Point operator-(const Point& other) const { return Point(x - other.x, y - other.y, id); }
Point& operator+=(const Point& other) {
x += other.x;
y += other.y;
return *this;
}
Point& operator-=(const Point& other) {
x -= other.x;
y -= other.y;
return *this;
}
bool operator==(const Point& other) const { return x == other.x && y == other.y; }
};
std::vector<Point> points;
// std::vector<Point> workshop_points;
int half_plane(const Point& p) {
if (p.y > 0) return 1;
if (p.y < 0) return 0;
// y == 0
return (p.x >= 0) ? 1 : 0;
}
int cross(const Point& a, const Point& b) {
return a.x * b.y - a.y * b.x;
}
int dot(const Point& a, const Point& b) {
return a.x * b.x + a.y * b.y;
}
int _abs(int a) {
if (a > 0) return a;
return -a;
}
// Compare directions (angle) of a and b without using reals.
// Returns true if angle(a) < angle(b) in [0, 2*pi) ordering.
bool angle_less(const Point& a, const Point& b) {
int ha = half_plane(a), hb = half_plane(b);
if (ha != hb) return ha > hb; // upper half-plane comes first
int cr = cross(a, b);
if (cr != 0) return cr > 0; // a before b if cross>0 (b is ccw from a)
// collinear same ray direction: tie-break deterministically by distance
// (closer first) — optional; it won't affect direction-only logic
int da = a.x * a.x + a.y * a.y;
int db = b.x * b.x + b.y * b.y;
return da < db;
}
// zwraca true jeśli angle(u,v) < angle(p,q)
// Returns true if the CCW angle from u to v is < CCW angle from p to q
bool angle_less2(const Point& u, const Point& v, const Point& p, const Point& q) {
int c1 = cross(u, v);
int c2 = cross(p, q);
int d1 = dot(u, v);
int d2 = dot(p, q);
// Handle collinear cases (cross==0)
if (c1 == 0 && c2 == 0) {
if (d1 >= 0 && d2 >= 0) return d1 < d2; // both 0..180
if (d1 < 0 && d2 >= 0) return false; // 180..360 > 0..180
if (d1 >= 0 && d2 < 0) return true; // 0..180 < 180..360
if (d1 < 0 && d2 < 0) return d1 > d2; // both >180, smaller angle = larger dot in negative
}
// Determine which quadrant the angle is in
// Angle is "less" if it is in smaller CCW rotation (0..360)
if (c1 >= 0 && c2 < 0) return true; // first in 0..180, second in 180..360
if (c1 < 0 && c2 >= 0) return false; // first in 180..360, second in 0..180
// Both in same half-plane: compare using cross/dot product
// angle(u,v) < angle(p,q) <=> c1*d2 < c2*d1
return (int)c1 * (int)d2 < (int)c2 * (int)d1;
}
Point reflect(const Point& p) {
return Point(-p.x, -p.y);
}
Point normalize(const Point& middle, const Point& p) {
return p - middle;
}
void solve() {
int n;
std::cin >> n;
if (n <= 3) {
return brut::solve(n);
}
points.resize(n);
// workshop_points.resize(n - 1);
// points.shrink_to_fit();
for (int i = 0; i < n; i++) {
int x, y;
std::cin >> x >> y;
// points[i] = {x, y, i};
points[i] = {x, y, i};
}
int total = 0;
// rozważ każdy punkt jako środek
for (int i = 0; i < n; i++) {
// i-ty punkt jako środek
// do workshop_points daj wszysttkie punkty oprócz i-tego
std::vector<Point> workshop_points;
workshop_points.reserve(n - 1);
for (int j = 0; j < n; ++j) {
if (j == i) continue;
workshop_points.push_back(normalize(points[i], points[j]));
}
int m = (int)workshop_points.size(); // m == n-1
// posortuj kątowo względem tego punktu
std::sort(workshop_points.begin(), workshop_points.end(), [](const Point& a, const Point& b) { return angle_less(a, b); });
// przypisz odpowiednie zbiorki
int num_L = 0, num_R = 0;
Point sum_L(0, 0), sum_R(0, 0);
int next_p_idx = -1, next_q_idx = -1;
Point origin(0, 0);
int idx = 0;
for (const auto& p : workshop_points) {
if (half_plane(p) == 1) {
sum_L += p;
num_L++;
if (next_p_idx == -1) {
next_p_idx = idx;
}
} else {
sum_R += p;
num_R++;
if (next_q_idx == -1) {
next_q_idx = idx;
}
}
idx++;
}
// duplicate array so we can walk circularly
workshop_points.resize(2 * m);
for (int k = 0; k < m; ++k)
workshop_points[m + k] = workshop_points[k];
if (next_p_idx == -1) next_p_idx = next_q_idx;
if (next_q_idx == -1) next_q_idx = next_p_idx;
// i co teraz?
// czas na zamiatanko!
Point prev_p(1, 0), prev_q(-1, 0);
int visited_num = 0;
while (visited_num != n - 1) {
if (angle_less2(prev_q, workshop_points[next_q_idx], prev_p, workshop_points[next_p_idx])) {
// uderza półprosta `q`
const auto& p = workshop_points[next_q_idx];
sum_R -= p;
sum_L += p;
prev_p = reflect(p);
prev_q = p;
next_q_idx++;
} else {
// uderza półprosta `p`
const auto& p = workshop_points[next_p_idx];
total += _abs(cross(p, sum_L));
total += _abs(cross(p, sum_R));
sum_L -= p;
sum_R += p;
prev_q = reflect(p);
prev_p = p;
next_p_idx++;
visited_num++;
}
}
}
int ans = total / 12;
int ans1 = 0;
if ((total / 6) & 1) ans1 = 5;
std::cout << ans << "." << ans1 << std::endl;
}
int32_t main() {
#ifndef GARY_DBG
std::ios_base::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
#endif
int t = 1;
// std::cin >> t;
for (; t > 0; t--) {
solve();
}
return 0;
}
namespace brut {
void solve(int n) {
for (int i = 1; i <= n; i++) {
int x, y;
std::cin >> x >> y;
points[i] = {x, y};
}
int total = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 1; k <= n; k++) {
if (i == j || i == k || k == j) continue;
int curr = llabs(points[i].first * (points[j].second - points[k].second) + points[j].first * (points[k].second - points[i].second) +
points[k].first * (points[i].second - points[j].second));
total += curr;
}
}
}
int ans = total / 12;
int ans1 = 0;
if ((total / 6) & 1) ans1 = 5;
std::cout << ans << "." << ans1 << std::endl;
}
}