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个,那么就是加上
2y−1
代码:
#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;
}