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 }
我自倾杯,君且随意
原文地址:https://www.cnblogs.com/nicetomeetu/p/5749706.html