zoukankan      html  css  js  c++  java
  • HDU 5738

    HDU 5738 - Eureka
    题意:

      包含两个以上共线的点的集合的个数

    分析:

      将所有点按(x,y)双关键字排序,排完序后所有j>i均满足xj>xi ,则接下来不会重复计数

      将所有j>i的点按相对于Pi的极角排序,再逆时针扫描每条线统计

      

      每条线的左端点Pi必须被计数,右边共m个点至少取一点为2^m -1.

      因为有重点,用map记录每个点的数目.

      此时重点对右侧的点没有影响,共n个左端点上至少取一点.

      再加上只选取重点, (2^n - n - 1), (总状态数 - 只选取一点的状态数 - 一点都不选状态数).

      所以总计(n-1)*(2^m-1) + (2^n - n - 1)。 

      这样枚举所有的线

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <map>
     7 using namespace std;
     8 #define LL long long
     9 const double eps = 1e-8;
    10 const double PI = 4 * atan(1);
    11 const int MOD = 1e9+7;
    12 struct Point
    13 {
    14     LL x,y;
    15     bool operator < (const Point &b) const
    16     {
    17         return x==b.x? y<b.y : x<b.x; 
    18     }
    19 }p[1005],pp[1005];
    20 int t,n,pos;
    21 LL pow2[1005],ans;
    22 map<Point,int> mp;
    23 bool ccmp(const Point& a,const Point& b){//极角排序
    24     LL dx1 = a.x - p[pos].x;
    25     LL dy1 = a.y - p[pos].y;
    26     LL dx2 = b.x - p[pos].x;
    27     LL dy2 = b.y - p[pos].y;
    28     return dx2 * dy1 < dx1 * dy2; 
    29 }
    30 bool Line(const Point &a,const Point &b,const Point &c){//判断共线
    31     LL dx1 = b.x - a.x;
    32     LL dy1 = b.y - a.y;
    33     LL dx2 = c.x - a.x;
    34     LL dy2 = c.y - a.y;
    35     return dx2 * dy1 == dx1 * dy2;
    36 }
    37 int main()
    38 {
    39     pow2[0]=1;
    40     for(int i=1;i<=1000;i++) pow2[i] = (pow2[i-1] + pow2[i-1]) % MOD;
    41     scanf("%d",&t);
    42     while(t--)
    43     {
    44         scanf("%d",&n);
    45         mp.clear();
    46         for(int i=0;i<n;i++)
    47         {
    48             scanf("%lld%lld",&p[i].x,&p[i].y);
    49             mp[p[i]]++;
    50         } 
    51         sort(p,p+n);
    52         ans = 0;
    53         for(int i=0;i<n;i++)
    54         {
    55             i+=mp[p[i]]-1;//最后一个重点 
    56             pos = i;
    57             memcpy(pp,p,sizeof(p));
    58             sort(pp + i + 1, pp + n, ccmp);//极角排序 
    59             int u = i+1;
    60             while(u<n)
    61             {
    62                 int v = u + 1;
    63                 while(v<n && Line(pp[i],pp[u],pp[v]) ) v++;//找到边界
    64                 int m = mp[ p[i] ];
    65                 ans = (ans + (pow2[v-u] - 1) * (pow2[m] - 1) % MOD ) %MOD;        
    66                 u = v;
    67             }
    68             int m = mp[p[i]];
    69             ans = (ans + pow2[m] - m - 1 )%MOD; //只选取重点 
    70         }
    71         printf("%lld
    ",ans); 
    72     }
    73     return 0;
    74 }
    我自倾杯,君且随意
  • 相关阅读:
    int.Parse()及其异常判断
    三个框框的EditBox
    等价类的划分方法与EditorBox问题等价类划分
    初学软件测试
    软件测试方法的分类细谈
    浅谈软件测试之回归测试
    白盒测试——基本路径法
    初探灰盒测试——介于白盒测试与黑盒测试的测试
    对闰年测试的非法输入处理的思考
    等价类测试——进一步完善的Web输入合法验证
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/5749706.html
Copyright © 2011-2022 走看看