https://loj.ac/problem/3054this
魚題,勁啊。spa
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <cmath> #include <set> #include <vector> using namespace std; #define N 2050 typedef double f2; typedef long long ll; const f2 eps=1e-10; const f2 pi=acos(-1); ll ans; int c[N],n,lb,len[N]; ll rlen[N],V[N]; ll pf(ll x) {return x*x;} ll gcd(ll x,ll y) {return y?gcd(y,x%y):x;} struct Point { ll x,y; Point(){} Point(ll x_,ll y_) {x=x_,y=y_;} Point turn90(const Point &p) const { Point re,t=*this-p; re.x=-t.y; re.y=t.x; return re+p; } void prt() { printf("%lld %lld\n",x,y); } Point operator + (const Point &u) const {return Point(x+u.x,y+u.y);} Point operator - (const Point &u) const {return Point(x-u.x,y-u.y);} Point operator / (const ll &rate) const {return Point(x/rate,y/rate);} ll operator | (const Point &u) const {return (x*u.y-y*u.x);} ll operator & (const Point &u) const {return (x*u.x+y*u.y);} }a[N]; struct Pop { Point p; f2 k; Pop() {} Pop(Point p_,f2 k_) {p=p_,k=k_;} bool operator < (const Pop &u) const { return k<u.k; } }b[N<<1]; struct B { ll a,b,c,x; void prt() { printf("%lld %lld %lld %lld\n",a,b,c,x); } bool operator < (const B &u) const { if(a==u.a) { if(b==u.b) { if(c==u.c) { return x<u.x; }else return c<u.c; }else return b<u.b; }else return a<u.a; } }; ll Abs(ll x) {return x>0?x:-x;} vector<B> S,T; B calc(Point p1,Point p2) { ll dy=p2.y-p1.y,dx=p2.x-p1.x; ll ta=-dy,tb=dx; ll d=gcd(Abs(ta),Abs(tb)); if(d!=1) ta/=d,tb/=d; if(ta<0) ta=-ta,tb=-tb; if(ta==0) tb=Abs(tb); ll tc=ta*p1.x+tb*p1.y; return (B){ta,tb,tc,0}; } int main() { scanf("%d",&n); int i,j; for(i=1;i<=n;i++){ scanf("%lld%lld",&a[i].x,&a[i].y); a[i].x<<=1, a[i].y<<=1; } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) if(i!=j) { Point mid=(a[i]+a[j])/2; B tmp=calc(a[i].turn90(mid),a[j].turn90(mid)); tmp.x=(a[i].x+a[j].x)/2; S.push_back(tmp); tmp.x=(a[i].y+a[j].y)/2; T.push_back(tmp); //printf("%d %d %lld %lld %lld\n",i,j,tmp.a,tmp.b,tmp.c); } } sort(S.begin(),S.end()); sort(T.begin(),T.end()); for(i=1;i<=n;i++) { Point o=a[i]; lb=0; for(j=1;j<=n;j++) if(i!=j) b[++lb]=Pop(a[j],atan2(a[j].y-a[i].y,a[j].x-a[i].x)); sort(b+1,b+lb+1); for(j=1;j<=lb;j++) b[j+lb]=b[j],b[j+lb].k+=2*pi; int ln=lb<<1; int l=0,r=0; for(j=1;j<=lb;j++) { rlen[j]=pf(o.x-b[j].p.x)+pf(o.y-b[j].p.y); V[j]=rlen[j]; } sort(V+1,V+lb+1); int lv=unique(V+1,V+lb+1)-V-1; for(j=1;j<=lb;j++) len[j]=lower_bound(V+1,V+lv+1,rlen[j])-V; for(j=1;j<=lb;j++) len[j+lb]=len[j]; for(j=1;j<=lv;j++) c[j]=0; ll ans1=0,ans2=0; for(j=1;j<=lb;j++) { for(;r<=ln&&b[r+1].k+eps<b[j].k+1.5*pi;) r++,ans1+=c[len[r]],c[len[r]]++; for(;l<=ln&&b[l+1].k<b[j].k+0.5*pi+eps;) l++,c[len[l]]--,ans1-=c[len[l]]; B t=calc(o,b[j].p),tl=t,tr=t; if(o.x==b[j].p.x) { tl.x=o.y, tr.x=b[j].p.y; if(tl.x>tr.x) swap(tl.x,tr.x); ans2=lower_bound(T.begin(),T.end(),tr)-upper_bound(T.begin(),T.end(),tl); }else { tl.x=o.x, tr.x=b[j].p.x; if(tl.x>tr.x) swap(tl.x,tr.x); ans2=lower_bound(S.begin(),S.end(),tr)-upper_bound(S.begin(),S.end(),tl); } ans2=max(ans2,0ll); //printf("%lld %lld\n",ans1,ans2); ans+=ans1*ans2; } } printf("%lld\n",ans<<1); }