hihoCoder#1879 : Rikka with Triangles (计算几何)

n<=2000,肯定没有办法把所有三角形找出来全判一遍

对于三角形的三个角,分别计算贡献,锐角的贡献是1倍面积,钝角的贡献是-2倍面积,这样算出角的贡献之后除以3就可以了

每次选择一个点为中心点,极角排序,维护一个锐角和钝角的坐标和,边扫边算贡献

#include <bits/stdc++.h>
#define ll long long
#define big __int128
#define eps 1e-8
#define mod 998244353
using namespace std;
const int maxn = 2005;
int sgn(double x)
{
    if (fabs(x) < eps)
        return 0;
    if (x < 0)
        return -1;
    return 1;
}
struct Point
{
    big x, y;
    Point() {}
    Point(big _x, big _y)
    {
        x = _x;
        y = _y;
    }
    Point operator+(const Point &b) const
    {
        return Point(x + b.x, y + b.y);
    }
    Point operator-(const Point &b) const
    {
        return Point(x - b.x, y - b.y);
    }
    big operator*(const Point &b) const
    {
        return x * b.x + y * b.y;
    }
    big operator^(const Point &b) const
    {
        return x * b.y - y * b.x;
    }
    void Mod()
    {
        bool tx = false, ty = false;
        if (x < 0)
        {
            x = -x;
            tx = true;
        }
        if (y < 0)
        {
            y = -y;
            ty = true;
        }
        x %= mod;
        y %= mod;
        if (tx)
            x = -x;
        if (ty)
            y = -y;
    }
    int getxx()
    {
        if (x > 0 && y >= 0)
            return 1;
        if (x <= 0 && y > 0)
            return 2;
        if (x < 0 && y <= 0)
            return 3;
        if (x >= 0 && y < 0)
            return 4;
        return 5;
    }
} a[maxn],del[maxn];
bool cmp(Point &a,Point &b){
    if(a.getxx() != b.getxx()){
        return a.getxx() < b.getxx();
    }else{
        return (a^b)>0;
    }
}
int n;
big ans;
void gao(int id){
    Point now = a[id];
    int m = 0;
    for(int i = 1;i <= n;i++){
        if(i==id)continue;
        del[++m] = a[i]-now;
        //del[m].Mod();
    }
    if(m<=1)return;
    sort(del+1,del+1+m,cmp);
    int p1 = 1,p2 = 1;
    Point s1=del[1],s2=del[1],ts1,ts2;
    for(int i = 1;i <= m;i++){
        int nxt;
        while(true){
            nxt = p1+1;
            if(nxt>m)nxt=1;
            if(nxt==i)break;
            if(!((del[i]^del[nxt])>=0&&(del[i]*del[nxt])>0))break;
            if((del[i]^del[nxt])==0&&(del[i]^del[p1])!=0)break;
            p1=nxt;s1=s1+del[p1];
        }
        while(true){
            nxt = p2+1;
            if(nxt>m)nxt=1;
            if(nxt==i)break;
            if(!((del[i]^del[nxt])>=0))break;
            if((del[i]^del[nxt])==0&&(del[i]^del[p2])!=0)break;
            p2=nxt;s2=s2+del[p2];
        }
        ts1=s1;ts2=s2-s1;ts1.Mod();ts2.Mod();
        ans+=(del[i]^ts1);ans %= mod;
        ans-=(del[i]^ts2)%mod*2ll%mod;
        ans=(ans+mod)%mod;
        if(p1==i){p1++;s1=s1+del[p1];}s1=s1-del[i];
        if(p2==i){p2++;s2=s2+del[p2];}s2=s2-del[i];
    }

}
int main()
{
    int T;
    scanf("%d",&T);
    big inv = (mod+1)/3;
    while (T--)
    {
        scanf("%d",&n);
        ans=0;
        for (int i = 1; i <= n; i++)
        {
            ll x, y;
            scanf("%lld%lld",&x,&y);
            a[i] = Point(x, y);
        }
        
        for(int i= 1;i <= n;i++){
            gao(i);
        }
        ans=(ans*inv)%mod;
        ll t = ans;
        printf("%lld\n",t);
    }
    return 0;
}

 

posted @ 2019-10-21 11:45  ACforever  阅读(408)  评论(0编辑  收藏  举报