Problem Statement | |||||||||||||
We have chosen a finite set of points in the plane. You are given their coordinates in the vector <int>s x and y: for each valid i, there is a point with coordinates (x[i],y[i]). We are interested in triangles with the following properties:
| |||||||||||||
Definition | |||||||||||||
| |||||||||||||
Limits | |||||||||||||
| |||||||||||||
Constraints | |||||||||||||
- | x and y will contain between 3 and 2500 elements, inclusive. | ||||||||||||
- | x and y will contain the same number of elements. | ||||||||||||
- | Each element of x and y will be between -10,000 and 10,000, inclusive. | ||||||||||||
- | No two points will be the same. | ||||||||||||
- | No three points will be collinear. | ||||||||||||
- | No point will be on the origin. | ||||||||||||
- | There will be no two points P and Q such that P, Q, and the origin are collinear. | ||||||||||||
Examples | |||||||||||||
0) | |||||||||||||
| |||||||||||||
1) | |||||||||||||
| |||||||||||||
2) | |||||||||||||
| |||||||||||||
3) | |||||||||||||
|
一个二维平面,给n个点,保证n个点两两不重合,保证没有点与原点重合,保证没有3点共线,保证没有两点和原点共线..
求有多少个三角形可以使得原点在三角形内。
此题并不通用,因为限制条件太多,不过解起来也比较好办。根据此题保证的条件,任意3个点都可以构成一个三角形,并且不可能有两个三角形重合,则一共有C(n,3)个三角形,C(n,3)个三角形中有的围住了原点,有的没有,只需减去没有的数量就是答案了。怎么统计没有的呢?枚举任意一个点A,其与原点可以构成一个向量OA,其余点B与原点构成的向量OB,OA与OB一定不共线,OA所在的直线把平面分成了两个部分,不妨以左部分为关键平面,算出平面中点的个数m,m个点中任意两个点可以和A构成一个唯一的三角形,则有C(m,2)个三角形,可以说明这C(m,2)个三角形一定不围住原点。可以说明对于每个OA,只需统计一半边中三角形个数,然后用C(n,3)减去每个C(m,2)就是答案。
代码如下:(建议自己写,不要看)
//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN
#define N 101000
#define M
struct Point
{
double x,y;
Point(){};
Point(double xx,double yy):x(xx),y(yy){};
}p[N];
typedef Point Vector;
double sq(double x){//x^2
return x*x;
}
int dcmp(double x){//判断x正负或为0
if(fabs(x)<eps) return 0;
else if(x<0) return -1;
else return 1;
}
Vector operator +(const Vector a,const Vector b){//两向量相加
return Vector(a.x+b.x,a.y+b.y);
}
Vector operator -(const Vector a,const Vector b){//两向量相减
return Vector(a.x-b.x,a.y-b.y);
}
bool operator ==(const Vector a,const Vector b){//判断两点或两向量是否一致
return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
double operator *(const Vector a,const Vector b){//两向量点乘
return a.x*b.x+a.y*b.y;
}
double operator &(const Vector a,const Vector b){//两向量叉积
return a.x*b.y-a.y*b.x;
}
Vector operator *(const Vector b,const double a){//一个数*一个向量
return Vector(a*b.x,a*b.y);
}
Vector operator *(const double a,const Vector b){//一个向量*一个数
return Vector(a*b.x,a*b.y);
}
class TrianglesContainOrigin{
public:
long long count(vector <int> x, vector <int> y){
ll len=gsize(x);
rep(i,0,len){
p[i]=Point(x[i],y[i]);
}
Point ori(0,0);
ll res=len*(len-1)*(len-2)/(6LL);
rep(i,0,len){
Vector v1=p[i]-ori;
ll num=0;
rep(j,0,len){
if(i==j) continue;
Vector v2=p[j]-ori;
if(dcmp(v1&v2)>0){
num+=1;
}
}
num=num*(num-1)>>1LL;
res-=num;
}
return res;
}
};