HDU5738

题意就是要找一条直线上的点,注意有重点;

注意运用第一个公式,因为第i个点必定要用到,其他的点用法有两种,只用i的重点和不止用i的重点

只用i的重点相当于从1开始取组合数

不止用i的重点则重点可以从0开始取组合数,非重点则从1开始取

#include <stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<map>
using namespace std;
typedef long long LL;
map<pair<LL,LL>,int>vis;
const int mod=1e9+7;
int t,n;
struct st{
LL x,y;
}num[1005];
bool cmp(st a,st b){
if(a.x==b.x)
    return a.y<b.y;
else
    return a.x<b.x;
}
LL gcd(LL a,LL b){
return b?gcd(b,a%b):a;
}

LL qpow(LL a,LL b){
    if(b<0)
        return 0;
    a%=mod;
    LL ans = 1;
    while(b) {
        if(b&1) ans = (ans * a) % mod;
        b >>= 1;
        a = (a * a) % mod;
    }
    return ans;
  }

int main()
{
    freopen("in.txt","r",stdin);
 cin>>t;
 while(t--){

    scanf("%d",&n);
    int i,j;
    for( i=1; i<=n; i++)
        scanf("%lld%lld",&num[i].x,&num[i].y);
    sort(num+1,num+1+n,cmp);
    LL ans=0;
    for( i=1; i<=n; i++){
        vis.clear();
        int res=1;
        for( j=i+1; j<=n; j++){
        if(num[j].x==num[i].x&&num[i].y==num[j].y)
            res++;
        else{
        LL dx=num[i].x-num[j].x;
        LL dy=num[i].y-num[j].y;
        LL gg=gcd(dx,dy);
        if(gg!=0){
            dx/=gg;
            dy/=gg;
        }
   
        vis[make_pair(dx,dy)]++;
        }
        }
        if(res>1){
        ans+=(qpow(2,res-1)-1)%mod;//第一种只用这个点的情况
        ans%=mod;
        }
     // cout<<ans<<" "<<i<<endl;

            for(map<pair<LL,LL>,int>::iterator it = vis.begin();it!=vis.end();it++)
            {
                LL cnt=(it->second);
                ans = (ans+((qpow(2,cnt)-1)*(qpow(2,res-1)))%mod)%mod;//用重点和其他点的情况
            }

    }
    cout<<ans<<endl;
 }
}
时间: 2024-10-31 22:42:47

HDU5738的相关文章

hdu-5738 Eureka(组合计数+极角排序)

题目链接: Eureka Time Limit: 8000/4000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Problem Description Professor Zhang draws n points on the plane, which are conveniently labeled by 1,2,...,n. The i-th point is at (xi,yi). Professor Zh