- double atan2(double y,double x) 返回的是原点至点(x,y)的方位角,即与 x 轴的夹角。返回值的单位为弧度,取值范围为(-π, π]。结果为正表示从 X 轴逆时针旋转的角度,结果为负表示从 X 轴顺时针旋转的角度。
- 理解多边形求面积的方法
题意:
给n个点,|x[i]|,|y[i]| <= 1e9。求在所有情况下的子集下(子集点数>=3),凸包的面积和。
分析:
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
const ll mod = 998244353;
const int maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
const double pi = 4 * atan(1);
struct point
{
ll x, y;
double angle;
point(ll a = 0, ll b = 0, double c = 0) : x(a), y(b), angle(c){}
bool operator< (const point& b)
{
return angle < b.angle;
}
point operator -(const point& b)
{
return point(x - b.x, y - b.y);
}
ll operator * (const point& b)
{
return x * b.y - y * b.x;
}
}a[maxn], b[maxn << 1];
ll p[maxn];
int n;
void make()
{
p[0] = 1;
for(int i = 1; i < maxn; i++) p[i] = p[i - 1] * 2 % mod;
for(int i = 0; i < maxn; i++) p[i] = (p[i] - 1 + mod) % mod;
}
int main()
{
int t; cin >> t;
make();
while(t--)
{
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i].x >> a[i].y;
ll res = 0;
for(int i = 1; i <= n; i++)
{
int tot = 0;
for(int j = 1; j <= n; j++)
{
if(i == j) continue;
b[++tot] = a[j];
b[tot].angle = atan2(a[j].y - a[i].y, a[j].x - a[i].x);
}
for(int k = 1; k <= tot; k++) b[k + tot] = b[k], b[k + tot].angle = b[k].angle + 2.0 * pi; //后面的需要用到前面的
sort(b + 1, b + 1 + tot + tot);
int l = 1, r = 1;
for(; l <= tot; l++)
{
while(b[r + 1].angle - b[l].angle < pi) r++;
res = (res + ((a[i].x * b[l].y - a[i].y * b[l].x) % mod + mod) % mod * p[r - l] % mod) % mod;
}
}
cout << res << endl;
}
}