题目:
Eureka
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1921 Accepted Submission(s): 568
Problem Description
Professor Zhang draws n points on the plane, which are conveniently labeled by 1,2,...,n. The i-th point is at (xi,yi). Professor Zhang wants to know the number of best sets. As the value could be very large, print it modulo 109+7.
A set P (P contains the label of the points) is called best set if and only if there are at least one best pair in P. Two numbers u and v (u,v∈P,u≠v) are called best pair, if for every w∈P, f(u,v)≥g(u,v,w), where f(u,v)=(xu−xv)2+(yu−yv)2−−−−−−−−−−−−−−−−−−−√ and g(u,v,w)=f(u,v)+f(v,w)+f(w,u)2.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤1000) -- then number of points.
Each of the following n lines contains two integers xi and yi (−109≤xi,yi≤109) -- coordinates of the i-th point.
Output
For each test case, output an integer denoting the answer.
Sample Input
3 3 1 1 1 1 1 1 3 0 0 0 1 1 0 1 0 0
Sample Output
4 3 0
Author
zimpha
Source
2016 Multi-University Training Contest 2
题意:
给定一些点,经过简单推导就可以知道题目是要求两两共线的点得几何的个数,结果模上1e9+7,。
解题思路:
这题不难,只是容易超时,我的写法是先用map缩点,再把不重合的点按横坐标优先排序,然后枚举点i,j(i<j),对以i为起点的向量极角排序,排完序之后统计必含i点且至少有一个元素的集合的个数。最后,因为题目要求元素个数至少为2,所以减去只含有一个元素的集合。
实现代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<map>
#include<string>
#include<queue>
#include<vector>
#include<list>
//#pragma comment(linker,"/STACK:1024000000,1024000000")
using namespace std;
#define INF 0x3f3f3f3f
int n;
const long long mod=1e9+7;
typedef pair<int,int> P;
struct Point {long long x,y;};
Point pp[1005];
Point ptmp[1005];
int cnt;
Point operator-(Point a,Point b)
{
return (Point){a.x-b.x,a.y-b.y};
}
Point operator+(Point a,Point b)
{
return (Point){a.x+b.x,a.y+b.y};
}
int cmp(Point a,Point b)
{
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
long long cross(Point& a,Point& b)
{
return a.x*b.y-a.y*b.x;
}
int cmp2(Point& a,Point& b) {return cross(a,b)<0;}
map<P,int>mp;
long long fac[1005];
int main()
{
int t;
scanf("%d",&t);
fac[0]=1;
for(int i=1;i<=1000;i++)
{
fac[i]=fac[i-1]*2;
fac[i]%=mod;
}
while(t--)
{
mp.clear();
scanf("%d",&n);
int cur=0;
long long ans=0;
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
if(mp[P(x,y)]==0) pp[++cur]=(Point){x,y};
mp[P(x,y)]++;
}
sort(pp+1,pp+1+cur,cmp);
for(int i=1;i<=cur;i++)
{
cnt=0;
for(int j=i+1;j<=cur;j++)
{
ptmp[++cnt]=pp[j]-pp[i];
}
sort(ptmp+1,ptmp+cnt+1,cmp2);
long long num=(fac[mp[P(pp[i].x,pp[i].y)]]-1+mod)%mod;
long long tmp=1;
int kk=0;
for(int j=1;j<=cnt+1;j++)
{
Point p=pp[i]+ptmp[j];
if(j==cnt+1||cross(ptmp[j],ptmp[j-1]))
{
ans+=num*tmp%mod;ans%=mod;
kk++;
tmp=fac[mp[P(p.x,p.y)]];
}
else if(j==1||cross(ptmp[j],ptmp[j-1])==0) tmp*=fac[mp[P(p.x,p.y)]],tmp%=mod;
}
ans=(ans-num*(kk-1)%mod+mod)%mod;
}
ans=(ans-n+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}