hdu 5738(扫描线)

#include <bits/stdc++.h>

#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;

#define LL long long
#define pii pair<int,int>
#define MP make_pair
#define ls i << 1
#define rs ls | 1
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define Pi acos(-1.0)
#define mod 1000000007
#define eps 1e-12
#define inf 0x3f3f3f3f
#define N 2010
#define M 1200020

int dcmp(double x){
    if(fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}
struct point{
    int x, y, id;
    double deg;
    point(int _x = 0, int _y = 0, int _id = 0){
        x = _x, y = _y, id = _id;
        deg = atan2(y * 1.0, x * 1.0);
    }
    bool operator < (const point &b) const {
        return x < b.x || x == b.x && y < b.y;
    }
    bool operator == (const point &b) const {
        return x == b.x && y == b.y;
    }
};
int n, a[N], id[N], pow2[N];
point p[N], pp[N];
int ans;
void add(int &x, int y){
    x += y;
    if(x >= mod) x -= mod;
    if(x < 0) x += mod;
}
bool cmp(point a, point b){
    return a.deg < b.deg;
}
void gao(point p[], int m, int xx){
    sort(p + 1, p + 1 + m, cmp);
    for(int i = 1, k = 0; i <= m; ++i){
        if(i > 1 && dcmp(p[i].deg - p[i-1].deg) == 0){
            k += a[p[i-1].id];
        }
        else k = 0;
         int x = (pow2[xx] - 1 + mod) % mod;
        int y = (pow2[a[p[i].id]] - 1 + mod) % mod;
        int z = pow2[k];
        add(ans, 1LL * x * y % mod * z % mod);
    }
}
int qpow(int x, int k){
    int ret = 1;
    while(k){
        if(k & 1) ret = 1LL * ret * x % mod;
        x = 1LL * x * x % mod;
        k >>= 1;
    }
    return ret;
}    
int main(){
    pow2[0] = 1;
    for(int i = 1; i < N; ++i)
        pow2[i] = pow2[i-1] * 2 % mod;
    int cas;
    scanf("%d", &cas);
    while(cas--){
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
            scanf("%d%d", &p[i].x, &p[i].y);
        sort(p + 1, p + 1 + n);
        int cnt = 1;
        p[cnt] = p[1], a[1] = 1;
        for(int i = 2; i <= n; ++i){
            if(p[i] == p[cnt]) a[cnt]++;
            else{
                p[++cnt] = p[i];
                a[cnt] = 1;
            }
        }
        n = cnt;
        int sum = 0;
        ans = 0;
        for(int i = 1; i <= n; ++i){
            if(a[i] >= 2){
                add(sum, pow2[a[i]] - 1 - a[i]);
            }
            int tot = 0;
            for(int j = 1; j <= n; ++j){
                if(i == j) continue;
                pp[++tot] = point(p[j].x - p[i].x, p[j].y - p[i].y, j);
            }
            gao(pp, tot, a[i]);
        }
        printf("%d\n", (int)(1LL * ans * qpow(2, mod-2) % mod + sum) % mod);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值