1个n边形的面积,可以3角剖分成n 个每一个边和原点构成的3角形的有向面积
这样每条边等于1个有向面积,那末问题转化成只要求每条边能作为几个凸包的边
那末枚举1点O,这样对任意1点X会有1条OX的边,而这条边构成凸包的数量,明显就是只能在和他夹角180度之内的边之内找,也就是有多少个点,就是2^num - 1(由于最少要有1个点)
因而进行极角排序,双指针扫1遍就可以得到所有答案
代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MOD = 998244353;
const int N = 1005;
const double pi = acos(⑴.0);
struct Point {
int x, y;
double ang;
void read() {
scanf("%d%d", &x, &y);
}
};
bool cmp(Point a, Point b) {
return a.ang < b.ang;
}
int t, n;
Point p[N], tmp[N * 2];
int pow2[N];
int area(Point a, Point b) {
return (((ll)a.x * b.y % MOD - (ll)a.y * b.x % MOD ) % MOD + MOD) % MOD;;
}
int main() {
scanf("%d", &t);
pow2[0] = 1;
for (int i = 1; i < N; i++)
pow2[i] = pow2[i - 1] * 2 % MOD;
while (t--) {
int ans = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++)
p[i].read();
for (int i = 0; i < n; i++) {
int tn = 0;
for (int j = 0; j < n; j++) {
if (i == j) continue;
tmp[tn] = p[j];
tmp[tn++].ang = atan2(p[j].y - p[i].y, p[j].x - p[i].x);
}
for (int j = 0; j < tn; j++) {
tmp[j + tn] = tmp[j];
tmp[j + tn].ang += pi * 2;
}
sort(tmp, tmp + tn * 2, cmp);
int r = 0;
for (int l = 0; l < tn; l++) {
while (tmp[r + 1].ang - tmp[l].ang < pi) r++;
ans = (ans + (ll)area(p[i], tmp[l]) * ((pow2[r - l] - 1 + MOD) % MOD) % MOD) % MOD;
}
}
printf("%d
", ans);
}
return 0;
}