牛客小白月赛 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编辑  收藏  举报

导航