hdu 5738 Eureka 极角排序

题目:

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值