Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
A regular polygon has all vertices on one circle. So whatever the answer is, your three pillars must lie on the circumcircle of the triangle they form.
If the polygon has sides, then adjacent vertices differ by a central angle of . Think about how many polygon edges lie on each arc between your three chosen vertices.
Let those arc gaps be with . Then the corresponding central angles are . By the inscribed angle theorem, the triangle's angles are
So for a candidate , you only need to check whether each triangle angle is an integer multiple of . Since the statement guarantees the optimal answer has , brute-forcing is completely fine.
Compute the triangle angles from the coordinates using the law of cosines, find the smallest valid , compute the circumradius of the triangle, then output The first valid is best, because for fixed , the area of an inscribed regular -gon increases with .
Any regular polygon is cyclic, so all its vertices lie on one circle. Therefore the unknown arena must use the circumcircle of the triangle formed by the three found pillars. Its circumradius is completely determined by the input.
Assume the answer is a regular -gon. Walking around the polygon, the three known vertices split the boundary into three chains of lengths , with
So the corresponding arcs on the circle have measures
Now let the triangle angles be . By the inscribed angle theorem, each triangle angle equals half of the opposite arc. Hence, after matching the order correctly,
So a candidate works iff each of is an integer multiple of .
Conversely, if are multiples of , then the three arcs are multiples of , so the three given points are vertices of some regular -gon on the same circumcircle.
That is the whole trick. The rest is just not messing up the floating point.
The statement literally tells us the optimal polygon has at most sides. So don't invent a floating-point gcd ritual unless you enjoy pain. Just try every and check whether are integers up to some small .
The first valid is optimal. For a fixed circumradius , the area of an inscribed regular -gon is
Let . Then
On , the function decreases as increases. When grows, shrinks, so grows. Therefore the smallest valid gives the smallest area. Nice and clean.
Let the side lengths of the triangle be
Compute the triangle angles with the law of cosines:
Clamp the cosine value to before calling , because floating point likes to be annoying.
Next, compute the triangle area from the cross product:
Then the circumradius is
Finally, once the smallest valid is found, the answer is
We try at most values of , each in . So the total complexity is with memory.
In other words: geometry problem, but the algorithm is basically constant time. Very Codeforces.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct Point {
ld x, y;
};
ld dist(Point a, Point b) {
ld dx = a.x - b.x;
ld dy = a.y - b.y;
return sqrtl(dx * dx + dy * dy);
}
ld cross(Point a, Point b, Point c) {
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
ld clamp1(ld x) {
if (x < -1.0L) return -1.0L;
if (x > 1.0L) return 1.0L;
return x;
}
bool nearInt(ld x) {
const ld EPS = 1e-6L;
return fabsl(x - roundl(x)) < EPS;
}
int main() { setIO();
Point p[3];
for (int i = 0; i < 3; ++i) {
cin >> p[i].x >> p[i].y;
}
const ld PI = acosl(-1.0L);
ld a = dist(p[1], p[2]);
ld b = dist(p[2], p[0]);
ld c = dist(p[0], p[1]);
ld A = acosl(clamp1((b * b + c * c - a * a) / (2.0L * b * c)));
ld B = acosl(clamp1((c * c + a * a - b * b) / (2.0L * c * a)));
ld C = acosl(clamp1((a * a + b * b - c * c) / (2.0L * a * b)));
int n = -1;
for (int cand = 3; cand <= 100; ++cand) {
ld step = PI / cand;
if (nearInt(A / step) && nearInt(B / step) && nearInt(C / step)) {
n = cand;
break;
}
}
ld triArea = fabsl(cross(p[0], p[1], p[2])) / 2.0L;
ld R = a * b * c / (4.0L * triArea);
ld ans = n * R * R * sinl(2.0L * PI / n) / 2.0L;
cout << fixed << setprecision(10) << ans << "\n";
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct Point {
ld x, y;
};
ld dist(Point a, Point b) {
ld dx = a.x - b.x;
ld dy = a.y - b.y;
return sqrtl(dx * dx + dy * dy);
}
ld cross(Point a, Point b, Point c) {
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
ld clamp1(ld x) {
if (x < -1.0L) return -1.0L;
if (x > 1.0L) return 1.0L;
return x;
}
bool nearInt(ld x) {
const ld EPS = 1e-6L;
return fabsl(x - roundl(x)) < EPS;
}
int main() { setIO();
Point p[3];
for (int i = 0; i < 3; ++i) {
cin >> p[i].x >> p[i].y;
}
const ld PI = acosl(-1.0L);
ld a = dist(p[1], p[2]);
ld b = dist(p[2], p[0]);
ld c = dist(p[0], p[1]);
ld A = acosl(clamp1((b * b + c * c - a * a) / (2.0L * b * c)));
ld B = acosl(clamp1((c * c + a * a - b * b) / (2.0L * c * a)));
ld C = acosl(clamp1((a * a + b * b - c * c) / (2.0L * a * b)));
int n = -1;
for (int cand = 3; cand <= 100; ++cand) {
ld step = PI / cand;
if (nearInt(A / step) && nearInt(B / step) && nearInt(C / step)) {
n = cand;
break;
}
}
ld triArea = fabsl(cross(p[0], p[1], p[2])) / 2.0L;
ld R = a * b * c / (4.0L * triArea);
ld ans = n * R * R * sinl(2.0L * PI / n) / 2.0L;
cout << fixed << setprecision(10) << ans << "\n";
}