这道题用转化补集的思想一下就很简单了
考虑不包括原点的三角形,显然对于一个点,它与原点构成的直线
在这条直线同侧的任意两点和这个点构成的三角形一定不是黄金三角形
为了避免重复我们只考虑直线上方的两点
然后我们只要按极角序扫一遍即可
1 type point=record 2 x,y:longint; 3 end; 4 5 var p:array[0..100010] of point; 6 ans,s,w:int64; 7 n,i,j:longint; 8 9 function cross(a,b:point):int64; 10 begin 11 exit(int64(a.x)*int64(b.y)-int64(b.x)*int64(a.y)); 12 end; 13 14 function cmp(a,b:point):boolean; //pascal判断极角的大小,没有atan这种函数哎 15 begin 16 if (a.y>0) and (b.y<=0) then exit(true); 17 if (b.y>0) and (a.y<=0) then exit(false); 18 if cross(a,b)>0 then exit(true); 19 exit(false); 20 end; 21 22 procedure sort(l,r:longint); 23 var i,j:longint; 24 x,y:point; 25 begin 26 i:=l; 27 j:=r; 28 x:=p[(l+r) shr 1]; 29 while i<=j do 30 begin 31 while cmp(p[i],x) do inc(i); 32 while cmp(x,p[j]) do dec(j); 33 if i<=j then 34 begin 35 y:=p[i]; 36 p[i]:=p[j]; 37 p[j]:=y; 38 inc(i); 39 dec(j); 40 end; 41 end; 42 if i<r then sort(i,r); 43 if j>l then sort(l,j); 44 end; 45 46 begin 47 readln(n); 48 for i:=1 to n do 49 readln(p[i].x,p[i].y); 50 sort(1,n); 51 j:=1; 52 for i:=1 to n do 53 begin 54 while cross(p[i],p[j mod n+1])>=0 do 55 begin 56 if j mod n+1=i then break; 57 j:=j mod n+1; 58 inc(w); 59 end; 60 s:=s+w*(w-1) div 2; 61 dec(w); 62 end; 63 ans:=int64(n)*int64(n-1) div 2*int64(n-2) div 3; 64 writeln(ans-s); 65 end. 66 67