HDU 5738 Eureka 极角排序,注意读题

来源:互联网 发布:sql中的聚合函数 编辑:程序博客网 时间:2024/06/05 07:59

题目大意:


平面给n<=1000个坐标,每个坐标值范围在[-1e9,1e9]之间


问,随便取一些点集,使得点集内的点,在一条直线上,有多少种方案。


方法:按照x,y坐标排序。x相同,y从小到大。


这样,我们从最左边的点开始,让这个点固定下来,求这个点必须取的情况下,在这个点的右边【和上方】的直线中有多少方案。


现在问题主要是,如何找一些经过原点的直线。(求K点的时候,把K点放在原点上) 


因为K点一定是最左边的,所以右边的点的X坐标都是大于等于0的,所有剩下的点可以极角排序,角度相同的,显然在一条线上了……


注意,有多个点在同一个点上的情况,要特殊处理一下。。。


#include <iostream>#include <ctime>#include <cstdio>#include <queue>#include <cstdlib>#include <algorithm>#include <cstring>#include <vector>#include <map>#include <string>using namespace std;typedef long long LL;const int maxn = 10e5 *4 + 10;const int mod = 1e9+7;int n;struct node{LL x, y;}a[1000 + 100], b[1000 + 100];bool cmp1(node A, node B){if (A.x == B.x)return A.y < B.y;return A.x < B.x;}void init(){scanf("%d", &n);for (int i = 1; i <= n; ++ i){scanf("%lld%lld", &a[i].x, &a[i].y);}sort(a + 1, a + 1 + n, cmp1);}bool cmp2(node A, node B)//极角排序{return B.x * A.y < B.y * A.x;}bool xie_que(node A, node B)//两点斜率是否相同 {return B.x*A.y == B.y*A.x;}LL powMod( LL a , LL b , LL p = mod  )//a^b % p{    LL r = 1 ;    a %= p ;    while( b )    {        if( b&1 ) r = r*a%p ;        b >>= 1 ;        a = a*a%p ;    }    return r ;}void doit(){LL ans = 0;for (int i = 1; i < n ;++ i){int t, j;for (j = i + 1; j <= n ;++ j)//把a.x,a.y移到原点{b[j].x = a[j].x - a[i].x;b[j].y = a[j].y - a[i].y;}LL same=0;t=0;for (j = i + 1; j <= n; ++ j)if (!b[j].x && !b[j].y){ ++ same;}else break;ans += powMod(2LL, same) -1;ans %= mod;if (j<=n){sort(b+j, b + n + 1, cmp2);while (j <= n){t = 1;while (j + 1 <= n && xie_que(b[j], b[j + 1])){++t;++j;}ans += powMod(2, same) * (powMod(2, t) - 1);ans %= mod;++j;}}}printf("%lld\n", ans);}int main(){    int T;    scanf("%d", &T);    while (T--)    {        init();        doit();    }    return 0;}




0 0
原创粉丝点击