牛客小白月赛 103 冰冰的分界线(乘法逆元解决除法精度不够的问题)
\[y=kx+b
\]
\[ k=\frac{x_1-x_2}{y_2-y_1} \quad \quad 中点为(\frac{x_1+x_2}{2} ,\frac{y_1+y_2}{2})
\]
\[ b=\frac{y_1+y_2}{2} -(\frac{x_1-x_2}{y_2-y_1} )*\frac{x_1+x_2}{2}
\]
\[通分一下写成 \quad b=\frac{y_2*y_2-y_1*y_1+x_2*x_2-x_1*x_1}{2*(y_2-y_1)}
\]
对b使用乘法逆元,那么则有1/x=qpow(x,mod-2),分子放外面乘,分母1/2*(y2-y1)使用快速幂,然后将[k,b],放入set去重即可,注意每一步都记得取模
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
using pii=pair<int,int>;
int qpow(int a,int n)
{
int res=1;
while(n)
{
if(n&1) res=res*a%mod;
a=a*a%mod;
n>>=1;
}
return res%mod;
}
pii getit(int x1,int y1,int x2,int y2)
{
int k;
//先特判斜率不存在 和斜率为0的情况
if(x1==x2) k=0;
else if(y1==y2) k=1e18;
else {
k=(x1-x2)*qpow(y2-y1,mod-2)%mod; //记得mod
}
int b=(y2*y2-y1*y1-x1*x1+x2*x2)*qpow(2*(y2-y1),mod-2)%mod;//记得mod
return {k,b};
}
void solve()
{
int n;
cin>>n;
vector<int>x(n),y(n);
set<pair<int,int> >se;
for(int i=0;i<n;i++) cin>>x[i];
for(int i=0;i<n;i++) cin>>y[i];
for(int i=0;i<n;i++) {
for (int j = i + 1; j < n; j++) {
auto [k,b]=getit(x[i],y[i],x[j],y[j]);
if(k==1e18) b=x[i]+x[j];
se.insert({k,b});
}
}
cout<<se.size()<<"\n";
}
signed main()
{
int t=1;
cin>>t;
while(t--)
{
solve();
}
}
posted on 2024-12-03 16:35 swj2529411658 阅读(4) 评论(0) 编辑 收藏 举报