https://nanti.jisuanke.com/t/A1283
怎么圆的反演全是2017出的题
以上面两个圆的切点为反演点,反演半径为R,那么左右两个圆就变成了lx=-R/2和rx=R/2的两条垂直的直线
然后与这左右两个圆相切的就是夹在两条直线之间的,又因为与下面的圆也相切,所以所有圆的半径都是R/2,纵坐标减一减就行
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;
inline int sgn(double x)
{
if(x>-eps && x<eps) return 0;
if(x>0) return 1;
else return -1;
}
struct point
{
double x,y;
point (double a=0,double b=0)
{
x=a;y=b;
}
point operator + (const point &b)const
{
return point(x+b.x,y+b.y);
}
point operator - (const point &b)const
{
return point(x-b.x,y-b.y);
}
point operator * (const double &t)const
{
return point(x*t,y*t);
}
};
struct circle
{
point o;
double r;
};
inline double sqr(double x){return x*x;}
inline double det(const point &a,const point &b)
{
return a.x*b.y-a.y*b.x;
}
inline double dist(const point &a,const point &b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
inline circle inversion(circle a,point p,double R)
{
circle res;
double d1=dist(p,a.o);
res.r=a.r*R*R/(sqr(d1)-sqr(a.r));
double d2=R*R/(d1-a.r)-res.r;
res.o=p+(a.o-p)*(d2/d1);
return res;
}
int k;
double R;
circle a,c,ans;
int main()
{
int t;double lx,rx;
while(~scanf("%d",&t))
{
if(t<0) return 0;
scanf("%lf",&R);
a.o=point(0,0);a.r=R;
lx=-R/2;rx=R/2;
c.o=point(0,-R*sqrt(3.0));c.r=R;
c=inversion(c,a.o,a.r);
for(int i=1;i<=t;i++)
{
scanf("%d",&k);
ans.o=point(0,c.o.y-k*R);
ans.r=R/2;
ans=inversion(ans,a.o,a.r);
printf("%d %d\n",k,(int)ans.r);
}
}
return 0;
}