2016多校&&HDU.5738

来源:互联网 发布:谁人知我心可免 编辑:程序博客网 时间:2024/05/14 23:35

【题意】

给你一些二维的点,判断多少个集合中存在一个好的点对,好的点对的定义为对于集合中任何一个点w(w≠u,w≠v),对于集合中的u,v都满足g(u,v,w)≥f(u,v)+f(u,w)+f(v,w)2。我们将式子化简一下为

f(u,v)>=f(u,w)+f(v,w)
我们知道两点之间线段最短,所以这个式子就是
f(u,v)=f(u,w)+f(v,w)
满足这个条件的集合个数,可以明显的看出这个集合中的所有的点一定是共线的,如果共线的点数为n,那么集合数目就是
ans=C(n2)+C(n3)+C(n4)+⋯+C(nn)=2n−1−n
如何处理出共线的点的数目?

【解题方法】

用map来记录对应斜率的线段的点的个数,然后枚举点,对每个点用map存下和这个店斜率相等的所有点,还有不要忘记最后处理这个点单独为重点的情况。

【AC code】


#include <map>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define ll long longconst int maxn=1010;const int mod=1e9+7;ll gcd(ll a,ll b){    return b==0?a:gcd(b,a%b);}struct node{    ll x,y;    node(){}    node(ll x,ll y):x(x),y(y){}    bool operator <(const node &a)const{        return x==a.x?y<a.y:x<a.x;    }    bool operator ==(const node &a)const{        return (x==a.x&&y==a.y);    }    node operator -(const node &a)const{        return node(x-a.x,y-a.y);    }    node operator *(const ll &a)const{        return node(x*a,y*a);    }    node operator /(const ll &a)const{        return node(x/a,y/a);    }}p[maxn];int cnt[maxn];//统计重点数量ll mi[maxn];//预处理二分幂map<node,ll>mp;//记录每一个对应斜率对应的点数ll ans;//记录答案void init(){    memset(cnt,0,sizeof(cnt));    mi[0]=1;    for(int i=1; i<=1000; i++) mi[i]=(mi[i-1]*2)%mod;}int main(){    init();    int T,n;    scanf("%d",&T);    while(T--){        scanf("%d",&n);        memset(cnt,0,sizeof(cnt));        cnt[0]=1;        for(int i=0; i<n; i++) scanf("%I64d%I64d",&p[i].x,&p[i].y);        int m=0;        sort(p,p+n);        for(int i=1; i<n; i++){            if(p[m]==p[i]) cnt[m]++;            else{                p[++m]=p[i];                cnt[m]++;            }        }        node now;        ans=0;        if(m==0){            ans=mi[cnt[0]]-1-cnt[0];            printf("%I64d\n",ans);            continue;        }else{            for(int i=0; i<=m; i++){                mp.clear();                for(int j=i+1; j<=m; j++){                    now=p[i]-p[j];                    //统一向量                    if(now.x<0) now=now*(-1);                    //向量化简                    ll g=gcd(abs(now.x),abs(now.y));                    now=now/g;                    mp[now]+=cnt[j];                }                //在起点中选出至少一个数和共线的至少选出一个数组合                for(auto it=mp.begin(); it!=mp.end(); it++){                    ans=(ans+(((mi[cnt[i]]-1)*(mi[it->second]-1))%mod)%mod)%mod;                }                //处理重点                ans=(ans+(mi[cnt[i]]-1-cnt[i]))%mod;            }            printf("%I64d\n",ans);        }    }}


0 0
原创粉丝点击