Editorial for Diện Tích Bao Lồi
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for(int i = a; i < (b); ++i) #define all(x) begin(x), end(x) #define sz(x) (int)(x).size() typedef long long ll; typedef pair<int, int> pii; typedef vector<int> vi; template <class T> int sgn(T x) { return (x > 0) - (x < 0); } template<class T> struct Point { typedef Point P; T x, y; explicit Point(T x=0, T y=0) : x(x), y(y) {} bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); } bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); } P operator+(P p) const { return P(x+p.x, y+p.y); } P operator-(P p) const { return P(x-p.x, y-p.y); } P operator*(T d) const { return P(x*d, y*d); } P operator/(T d) const { return P(x/d, y/d); } T dot(P p) const { return x*p.x + y*p.y; } T cross(P p) const { return x*p.y - y*p.x; } T cross(P a, P b) const { return (a-*this).cross(b-*this); } T dist2() const { return x*x + y*y; } double dist() const { return sqrt((double)dist2()); } // angle to x-axis in interval [-pi, pi] double angle() const { return atan2(y, x); } P unit() const { return *this/dist(); } // makes dist()=1 P perp() const { return P(-y, x); } // rotates +90 degrees P normal() const { return perp().unit(); } // returns point rotated 'a' radians ccw around the origin P rotate(double a) const { return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); } friend ostream& operator<<(ostream& os, P p) { return os << "(" << p.x << "," << p.y << ")"; } friend istream& operator>>(istream& is, P& p) { return is >> p.x >> p.y; } }; typedef Point<ll> P; vector<P> convexHull(vector<P> pts) { if (sz(pts) <= 1) return pts; sort(all(pts)); vector<P> h(sz(pts)+1); int s = 0, t = 0; for (int it = 2; it--; s = --t, reverse(all(pts))) for (P p : pts) { while (t >= s + 2 && h[t-2].cross(h[t-1], p) <= 0) t--; h[t++] = p; } return {h.begin(), h.begin() + t - (t == 2 && h[0] == h[1])}; } template<class T> T polygonArea2(vector<Point<T>>& v) { T a = v.back().cross(v[0]); rep(i,0,sz(v)-1) a += v[i].cross(v[i+1]); return a; } ll ccw(P a, P b, P c) { return (b - a).cross(c - a); } bool half(P p) { return p.y > 0 || (p.y == 0 && p.x >= 0); } bool cmpPolar(const P &a, const P &b) { return make_tuple(half(a), 0, a.dist2()) < make_tuple(half(b), a.cross(b), b.dist2()); } // check if point p is between a and b bool between(const P &a, const P &b, const P &p) { ll da = (b - a).dot(a); ll db = (b - a).dot(b); ll dp = (b - a).dot(p); if (da > db) swap(da, db); return (da <= dp && dp <= db); } const int MOD = (int)1e9 + 7; void solve() { int n; scanf("%d", &n); vector<P> pt(n); for(int i = 0; i < n; ++i) { cin >> pt[i]; } vector<ll> e2(n+1); e2[0] = 1; for(int i = 1; i <= n; ++i) { e2[i] = (e2[i-1] * 2) % MOD; } ll ans = 0; for(int i = 0; i < n; ++i) { P origin = pt[i]; P zero = P{0, 0}; vector<P> d; for(int j = 0; j < n; ++j) { if (i != j) d.push_back(pt[j] - origin); } sort(all(d), cmpPolar); int k = d.size(); int r = 0; for(int l = 0; l < k; ++l) { if (l == r) ++r; while (r - l < k) { ll dir = d[l].cross(d[r%k]); if (!(dir > 0 || (dir == 0 && !between(zero, d[l], d[r%k])))) break; ++r; } // printf("l, r: %d %d\n", l, r); int cnt = r - l - 1; ll val = origin.cross(d[l] + origin) % MOD; ll contribute = e2[cnt] % MOD; // cout << origin << " " << d[l] + origin << endl; // printf("val, cnt: %lld %d\n", val, cnt); ans = (ans + val * contribute) % MOD; ans = (ans + MOD) % MOD; } } cout << ans << endl; } int main() { int t; scanf("%d", &t); while (t--) solve(); return 0; }
Comments