高清图片,新窗口打开吧。
BZOJ持续阵亡。
我写个暴力把外心的通式算出来了。。何必。。联立解两条直线就行了嘛。手推还容易错。..
题解上说的还是比较清楚了。。
极角排序不能直接用叉乘。。 atan2吧,就是速度比较慢。先预处理出来atan2值,不要在cmp里面算。
#include <cmath>
#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
typedef long long LL;
const int MAX_N=1505;
struct Point{
int x,y;double angle;
Point(int _x = 0,int _y = 0):x(_x),y(_y){}
void read(){scanf("%d%d",&x,&y);}
};
Point operator -(const Point &a,const Point &b){return Point(a.x-b.x,a.y-b.y);}
LL Cross(const Point &a,const Point &b){return (LL)a.x*b.y-(LL)a.y*b.x;}
bool cmp_PolarAngle(const Point &a,const Point &b){return a.angle<b.angle;}
int n,top;
Point a[MAX_N],r[MAX_N];
LL Ao,Tu;
int main(){
freopen("signaling.in","r",stdin);
freopen("signaling.out","w",stdout);
scanf("%d",&n);
rep(i,1,n) a[i].read();
rep(i,1,n){
top=0;
rep(j,1,n){
if (i==j) continue;
r[++top]=a[j]-a[i];
r[top].angle=atan2(r[top].y,r[top].x);
}
std::sort(r+1,r+top+1,cmp_PolarAngle);
LL res=(LL)(n-1)*(n-2)*(n-3)/6;
int in=0,k=2;
rep(j,1,top){
if (j==k) k=k%top+1;
while(Cross(r[j],r[k])>0)
if (++in,++k>top) k-=top;
if (in>=2) res-=(LL)(in-1)*in/2;
if (in) in--;
}
Ao+=res;
}
Tu=(LL)n*(n-1)*(n-2)*(n-3)/24-Ao;
printf("%f\n",(Ao+Tu*2)/((double)n*(n-1)*(n-2)/6)+3);
}