题面:https://codeforces.com/problemset/problem/1284/E
题解:
考虑一个五元组形成凸包的情况。
由于三点不共线,因此只可能有三种情况:
1.凸包含有3个点:此时贡献为2;
2.凸包含有4个点:贡献为1;
3.凸包含有5个点:贡献为0。
设这三种情况的个数分别为\(x_3\),\(x_4\),\(x_5\),
那么答案即为2\(x_3\)+\(x_4\)。
这个东西很不好求,考虑转化。
首先发现\(x_3\)+\(x_4\)+\(x_5\)=\(C(n,5)\)
其次,发现如果能求出3\(x_3\)+4\(x_4\)+5\(x_5\),
那答案就很容易求出。这个式子的几何意义即为
\(\sum\)每一条边所在的凸包数。
用双指针求出这个东西即可。
时间复杂度:O(\(n^2\)logn)
代码:
#include<bits/stdc++.h>
using namespace std;
#define re register ll
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline ll
#define STS system("pause")
template<class D>I read(D &res){
res=0;register D g=1;register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')g=-1;
ch=getchar();
}
while(isdigit(ch)){
res=(res<<3)+(res<<1)+(ch^48);
ch=getchar();
}
res*=g;
}
typedef pair<ll,ll>pii;
struct Vec{
ll x,y;
Vec(ll _x=0,ll _y=0){x=_x;y=_y;}
friend Vec operator + (Vec a,Vec b){return Vec(a.x+b.x,a.y+b.y);}
friend Vec operator - (Vec a,Vec b){return Vec(a.x-b.x,a.y-b.y);}
friend ll operator ^ (Vec a,Vec b){return a.x*b.y-a.y*b.x;}
friend bool operator < (Vec a,Vec b){
pii A=make_pair(a.x,a.y),B=make_pair(b.x,b.y);
bool c=A<make_pair(0ll,0ll),d=B<make_pair(0ll,0ll);
return c==d?(a^b)>=0:c<d;
}
}p[2550];
vector<Vec>v;
ll n,m,ans,cnt;
IN C(ll x,ll y){
re res=1;
F(i,0,y-1){res*=(x-i);res/=(i+1);}
return res;
}
int main(){
read(n);
F(i,1,n)read(p[i].x),read(p[i].y);
F(i,1,n){
v.clear();
F(j,1,n){
if(i==j)continue;
v.emplace_back(p[j]-p[i]);
}
sort(v.begin(),v.end());
m=0;
F(j,0,v.size()-1){
while(m<j+v.size()&&(v[j]^v[m%v.size()])>=0)m++;
cnt+=C(m-j-1,3);
}
}
ans=C(n,5)*5ll-cnt;
cout<<ans;
return 0;
}