HDU 5738 Eureka(map瞎搞)

http://acm.hdu.edu.cn/showproblem.php?pid=5738
题意:让你求集合的数量,在这个集合里有一对点,然后其余所有点,都在这两点的线段上。


题解:总的来说就是求共线问题,为了不重复计算,我们枚举i的时候,只考虑从i+1到n的点,考虑共线,就要进行极角排序,但是可能会有精度误差,如果用double的话,就会GG,所以我选择了map存 pair<a/gcd(a,b),b/gcd(a,b)> ,然后一定不能忘记的是,必须把斜率的第一维都统一到正数,为什么呢,因为对于(0,0)来说,(1,1)和(-1,-1)是共线的但是不统一的话就不一样了,然后我犯了个很大的错误,就是第一维是0的时候,应该把第二维小于0的统一到正数QAQ,这里错了好久,还有就是重复点的处理,因为如果有重复点,那么斜率就是<0,0>,但是它其实又是和其他所有点都共线,这时候就需要把这个当前基准的这个点重复的点,就记录,然后最后计算的时候,加进去就好了, 然后对于一个斜率,每加入一个点,就考虑必选这个点,和必选基准点,然后这个斜率上还有x个点,那就是可选可不选,加上y个重复点,也是可选可不选,就每次都加上 2x+y ,最后考虑不选这些点,只选重复点,重复点有y个,那么就是加上 2y1


代码:

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           1005
#define   MAXN          1000005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/

int x[MAX],y[MAX];
struct PP{
    int x,y;
}u;
map<pii,int> ma;
struct Node{
    LL dis;
    int x,y;
    bool operator < (const Node&a)const{
        return dis<a.dis;
    }
}p[MAX];
LL fact[1005];

void init(){
    fact[0]=1;
    for(int i=1;i<=1000;i++) fact[i]=fact[i-1]*2%mod;
}
int gcd(int a,int b){
    if(!b) return a;
    return gcd(b,a%b);
}
int main(){
    //freopen("in.txt","r",stdin);
    int t;
    cin>>t;
    //cout<<fabs(atan2(2,1)-atan2(-2,-1))<<endl;
    init();
    while(t--){
        int n;
        cin>>n;
        for(int i=0;i<n;i++){
            scanf("%d%d",&x[i],&y[i]);
            //x[i]=y[i]=0;
        }
        LL ans=0;
        for(int i=0;i<n;i++){
            int tot=0;
            int num=0;
            for(int j=i+1;j<n;j++){
                //if(i==j) continue;
                if(x[i]==x[j]&&y[i]==y[j]){
                    num++;
                    continue;
                }
                int flag=1;
                if(x[j]-x[i]<0||(x[j]-x[i]==0&&y[j]-y[i]<0)) flag=-1;
                p[tot++]=(Node){((LL)x[j]-x[i])*((LL)x[j]-x[i])+((LL)y[j]-y[i])*((LL)y[j]-y[i]),(x[j]-x[i])*flag,(y[j]-y[i])*flag};
            }
            sort(p,p+tot);
            ma.clear();
            for(int j=0;j<tot;j++){
                int k=gcd(abs(p[j].x),abs(p[j].y));
                ans+=fact[ma[mk(p[j].x/k,p[j].y/k)]+num];
                ma[mk(p[j].x/k,p[j].y/k)]++;
                if(ans>=mod) ans-=mod;
            }
            ans+=((fact[num]-1+mod)%mod);
            if(ans>=mod) ans-=mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值