题意:给了N条线(注意这些线有可能重合),问两条直线有交点的对数,1 3和3 1 属于同一对,两条直线重合也算有交点
解题思路:这道题有些细节是很恶心的 因为怕卡精度,所以直接用了pair存,用map套一个pair存储斜率,但是只存储斜率是不行的,因为直线有重合的情况,所以还得用map套两个pair存储k和b。y=kx+b{k=(y1-y2)/(x1-x2),b=(x2y1-x1y2)/(x2-x1)}。因为第i条直线最多和前面的i-1条直线相交,加上i-1条,减去斜率相同的条数,再加上减多的条数(k和b值都相同的)
代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define pi acos(-1.0)
#define e exp(1.0)
typedef long long ll;
typedef pair<ll,ll> pa;
const ll maxn=1e5+7;
const ll inf=0x3f3f3f3f;
ll T,N;
map<pair<pa,pa>,int>M;
map<pa,int>Mk;
inline ll read()
{
ll x=0,flag=1;
char c=getchar();
while(c>'9'||c<'0')
{
if(c=='-') flag=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
int main()
{
ios::sync_with_stdio(false);
T=read();
while(T--)
{
M.clear();
Mk.clear();
N=read();
ll i,j;
ll jie=0;
for(i=1;i<=N;i++)
{
ll x1,y1,x2,y2;
x1=read(),y1=read(),x2=read(),y2=read();
ll ka=y1-y2,kb=x1-x2;
ll ba=x2*y1-x1*y2,bb=x2-x1;
ll gcdk=__gcd(abs(ka),abs(kb));
ll gcdb=__gcd(abs(ba),abs(bb));
pa k;
if(ka==0)
k=make_pair(0,0);
else if(kb==0)
k=make_pair(inf,inf);
else
{
ka/=gcdk,kb/=gcdk;
if(ka*kb>0)
k=make_pair(abs(ka),abs(kb));
else
k=make_pair(-abs(ka),abs(kb));
}
pa b;
if(ba==0)
b=make_pair(0,0);
else if(bb==0)
b=make_pair(x1,x1);
else
{
ba/=gcdb,bb/=gcdb;
if(ba*bb>0)
b=make_pair(abs(ba),abs(bb));
else
b=make_pair(-abs(ba),abs(bb));
}
jie+=(i-1-Mk[k]+M[make_pair(k,b)]);
Mk[k]++;
M[make_pair(k,b)]++;
}
cout<<jie<<endl;
}
return 0;
}