您的位置:首页 > 大数据 > 人工智能

2016 Multi-University Training Contest 2 1005 hdu 5738 计算几何

2016-07-21 17:18 651 查看
链接:戳这里

Eureka

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

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

 

思路:

先去重,题目要求的集合是一条线段。并且u,v是线段的两个端点。那么对于点集的每一条线段,都统计每一条的贡献

设线段上有k个点,那么贡献为即(C(k,2)+C(k,3)+...+C(k,k))=2^k-1-k。但是在多条线段的交点处如果恰好是g个重点存在

那么我们需要减去多算的,设该重点恰好在m条线段上,那么多算了(m-1)次。多算的贡献为(m-1)*((2^g)-g-1)

问题就变成了一条线段上有多少个点以及一个点出现在多少线段上。直接n*nlogn处理

注意卡精度,开long double 吧

代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define mod 1000000007
#define INF (1ll<<60)-1
using namespace std;
const long double eps=1e-10;
int dcmp(long double x){
if(fabs(x)<=eps) return 0;
return x<0?-1:1;
}
struct point{
long double x,y;
point(long double x=0,long double y=0):x(x),y(y){}
bool operator < (const point &a)const{
if(dcmp(x-a.x)==0) return y<a.y;
return x<a.x;
}
};
bool operator == (const point &a,const point &b) {
if(fabs(a.x-b.x)<=eps && fabs(a.y-b.y)<=eps)
return true;
return false;
}
point s[1010],p[1010];
struct edge{
long double k,b;
int A,B;
bool operator < (const edge &a)const{
if(dcmp(k-a.k)==0) return b<a.b;
return k<a.k;
}
}e[1000100];
map<point,int> mp;
int q[1010];
ll Pow[1010];
int main(){
Pow[0]=1LL;
for(int i=1;i<=1000;i++) Pow[i]=Pow[i-1]*2LL%mod;
int T,n;
scanf("%d",&T);
while(T--){
mp.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++) {
cin>>s[i].x>>s[i].y;
mp[s[i]]++;
}
sort(s+1,s+n+1);
int cnt=0;
for(int i=1;i<=n;i++){
while(i+1<=n && s[i]==s[i+1]) i++;
p[++cnt]=s[i];
}
n=cnt;
cnt=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
point a=p[i],b=p[j];
if(dcmp(a.x-b.x)==0){
e[++cnt].k=INF*1.0;
e[cnt].b=a.x;
} else {
e[++cnt].k=(a.y-b.y)/(a.x-b.x);
e[cnt].b=a.y-e[cnt].k*a.x;
}
e[cnt].A=i;
e[cnt].B=j;
}
}
sort(e+1,e+cnt+1);
ll ANS=0;
mst(q,0);
for(int i=1;i<=cnt;i++){
int l=i;
while(dcmp(e[i].k-e[i+1].k)==0 && dcmp(e[i].b-e[i+1].b)==0 && i+1<=cnt){
i++;
}
int ans=0;
for(int j=l;j<=i;j++){
if(q[e[j].A]==0){
ans+=mp[p[e[j].A]];
q[e[j].A]=1;
}
if(q[e[j].B]==0){
ans+=mp[p[e[j].B]];
q[e[j].B]=1;
}
}
ANS=((ANS+Pow[ans]-1-ans)%mod+mod)%mod;
for(int j=l;j<=i;j++){
q[e[j].A]=0;
q[e[j].B]=0;
}
}
for(int i=1;i<=n;i++){
int tot=0,Num=0;
for(int j=1;j<=n;j++){
if(i==j) continue;
point a=p[i],b=p[j];
if(dcmp(a.x-b.x)==0){
e[++tot].k=INF*1.0;
e[tot].b=a.x;
} else {
e[++tot].k=(a.y-b.y)/(a.x-b.x);
e[tot].b=a.y-e[tot].k*a.x;
}
}
sort(e+1,e+tot+1);
for(int j=2;j<=tot;j++){
if(dcmp(e[j].k-e[j-1].k)==0 && dcmp(e[j].b-e[j-1].b)==0) continue;
Num++;
}
if (tot==0) ANS=(ANS+Pow[mp[p[i]]]-1-mp[p[i]])%mod;
else if(Num==0) {
/// if(n>1) continue;
/// ANS=((ANS+Pow[mp[p[i]]]-1-mp[p[i]])%mod+mod)%mod;
} else {
ANS=((ANS-Num*(Pow[mp[p[i]]]-1-mp[p[i]])%mod+mod)%mod+mod)%mod;
}
}
printf("%I64d\n",ANS);
}
return 0;
}
/*
10
5
1 0
2 0
3 0
4 0
5 0
3
1 1
1 1
1 1
3
0 0
0 1
1 0
1
0 0
7
2 5
4 4
4 4
2 2
2 2
2 2
4 1
9
2 5
2 5
4 4
4 4
4 4
4 1
2 2
2 2
2 2
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: