2016 Multi-University Training Contest 2 1005 hdu 5738 计算几何
来源:互联网 发布:js vr 插件 互动 编辑:程序博客网 时间:2024/06/06 00:34
链接:戳这里
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)-1using 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;}/*1051 02 03 04 05 031 11 11 130 00 11 010 072 54 44 42 22 22 24 192 52 54 44 44 44 12 22 22 2*/
0 0
- 2016 Multi-University Training Contest 2 1005 hdu 5738 计算几何
- 计算几何(组合计数+向量排序)——Eureka ( HDU 5738 ) ( 2016 Multi-University Training Contest 2 1005 )
- (HDU 5738) <计算几何 ,在n个点中找所有共线的集合> 2016 Multi-University Training Contest 2
- 2016 Multi-University Training Contest 2-1005---HDU 5738 Eureka
- hdu 5733 tetrahedron(2016 Multi-University Training Contest 1计算几何)
- HDU 5733 tetrahedron (2016 Multi-University Training Contest 1 计算几何)
- 2016 Multi-University Training Contest 1 1011(HDU 5733 计算几何)
- 2016 Multi-University Training Contest 1-1011---HDU 5733 tetrahedron(计算几何)
- 2016 Multi-University Training Contest 3 hdu 5762 Teacher Bo【计算几何】
- (HDU 5733)2016 Multi-University Training Contest 1 tetrahedron(几何)
- HDU 5738 Eureka (from: 2016 Multi-University Training Contest 2)
- HDU 3902 Swordsman 2011 Multi-University Training Contest 7 - Host by ECNU 计算几何
- hdu 4962 Closed Paths 计算几何 2014 Multi-University Training Contest 9-1003
- hdu 6055 简单计算几何,查找点的四种办法 2017 Multi-University Training Contest
- HDU 6055 Regular polygon(计算几何+思维)——2017 Multi-University Training Contest
- HDU 6127 Hard challenge(思维+计算几何)——2017 Multi-University Training Contest
- 2016 Multi-University Training Contest 2 1001 hdu 5734 暴力
- HDU 2016 Multi-University Training Contest 2 1001
- 利用FFmpeg制作视频序列
- bat批处理日期时间格式设置使用
- 十八Word实用技巧
- Vim 按键说明及帮助记忆
- Webpack + vue-loader构建单文件vue组件
- 2016 Multi-University Training Contest 2 1005 hdu 5738 计算几何
- 美团数据仓库-数据脱敏
- bocker中创建容器涉及的技术
- GDAL学习笔记—简单类封装
- windows mysql 自动备份的几种方法
- NSMutableArray使用注意
- Android自定义view详解
- Cocos2dx中的一些设计到内存管理的宏
- TextView下划线,EditText搜索