zoukankan      html  css  js  c++  java
  • hdu 5738 Eureka 极角排序+组合数学

    Eureka

    Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 2317    Accepted Submission(s): 678


    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,vP,uv) are called best pair, if for every wPf(u,v)g(u,v,w), where f(u,v)=(xuxv)2+(yuyv)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 (1n1000) -- then number of points.

    Each of the following n lines contains two integers xi and yi (109xi,yi109) -- 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
     
    Recommend
    wange2014   |   We have carefully selected several similar problems for you:  5762 5761 5760 5759 5758 
    题意:定义在同一直线上至少两个点(可以重合)就可以组成一个完美集合,比如点1,3,5共线,那么就有(1,3)(3,5)(1,5)和(1,3,5)四个集合,现在给你n个点的坐标,求有多少个这样的集合;
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <algorithm>
    #include <set>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long Ull;
    #define MM(a,b) memset(a,b,sizeof(a));
    const double eps = 1e-10;
    const int  inf =0x7f7f7f7f;
    const double pi=acos(-1);
    const int mod=1e9+7;
    const int maxn=100000+10;
    ll f_2[1000+10];
    
    struct Point{
        int x,y;
    }p[1000+10];
    
    struct Ang{
        double a;
        ll x,y;
    }ang[1000+10];
    
    bool cmpxy(Point a,Point b)
    {
        if(a.x!=b.x) return a.x<b.x;
        else return a.y<b.y;
    }
    
    bool cmpang(Ang a,Ang b){
        return a.a<b.a;
    }
    
    int main()
    {
        f_2[0]=1;
        for(int i=1;i<=1000;i++) f_2[i]=(f_2[i-1]*2)%mod;
        int cas,n;
        scanf("%d",&cas);
        while(cas--)
        {
            ll ans=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++) scanf("%d %d",&p[i].x,&p[i].y);
            sort(p+1,p+n+1,cmpxy);
    
            int i,j,k,l,num;
            for(i=1;i<n;i++)
            {
                for(j=i+1;j<=n;j++)
                {
                    if(p[j].x==p[i].x&&p[j].y==p[i].y) continue;
                    else break;
                }
                j--;
                int s=j-i+1,cnt=0,d=0;
                ans=(ans+f_2[s]-1-s)%mod;
                for(k=j+1;k<=n;k++)
                    {
                        ang[++cnt].a=atan2((double)(p[k].y-p[i].y),(double)(p[k].x-p[i].x));
                        ang[cnt].x=p[k].x;
                        ang[cnt].y=p[k].y;
                    }
    
                sort(ang+1,ang+cnt+1,cmpang);
                for(k=1;k<=cnt;k++){
    
                    for(l=k+1;l<=cnt;l++)
                    if((ang[l].y-p[i].y)*(ang[k].x-p[i].x)!=
                       (ang[k].y-p[i].y)*(ang[l].x-p[i].x))
                               {d++;break;}
                    l--;
                    num=l-k+1;
                    ans=(ans+((f_2[s]-1)*(f_2[num]-1))%mod)%mod;
                    k=l;
                }
    
                i=j;
            }
            printf("%lld
    ",ans%mod);
        }
        return 0;
    }
    

      思路:先对所有的点进行坐标排序,然后依次枚举每个点,先筛选出与其重合的点,然后,

    再依次为基点,求得没有枚举过得点相对这个点的角度,再进行极角排序,合并共线的点(这个

    判断共线容易错。不能直接根据相对基点角度(double型)是否相等来判断,可以直接用向量

    共线的坐标,变成相乘的形式

  • 相关阅读:
    [洛谷P2523] HAOI2011 Problem c
    [CF156D] Clues
    [洛谷P4769] NOI2018 冒泡排序
    [CF605E] Intergalaxy Trips
    [洛谷P4492] HAOI2018 苹果树
    [洛谷P3349] ZJOI2016 小星星
    [洛谷P4336] SHOI2016 黑暗前的幻想乡
    [洛谷P5364] SNOI2017 礼物
    [洛谷P2606] ZJOI2010 排列计数
    [洛谷P6078] CEOI2004 candy
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5708198.html
Copyright © 2011-2022 走看看