http://acm.hdu.edu.cn/showproblem.php?pid=6158
三角函数尤其是反三角函数又慢精度又差,能用比例向量和叉积甚至x/sqrt(sqr(x)+sqr(y))这种形式都比反三角函数好
这题以两个圆的左边切点为反演中心,大圆的直径为R,大圆的反演结果就是与大圆相切的一条直线,小圆就是更远处的直线,由于反演后的相切性不变,所以3个原反演出2条直线夹着一串圆,而且这些圆也要相切,他们的直径是rx-lx
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
const double pi=acos(-1.0);
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));
}
int n;
circle a,b;
double ans;
inline void prework()
{
scanf("%lf%lf",&a.r,&b.r);
if(a.r<b.r)
swap(a.r,b.r);
a.o=point(a.r,0);b.o=point(b.r,0);
scanf("%d",&n);
}
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;
}
inline void mainwork()
{
double lx=2*a.r,rx=(2*a.r)*(2*a.r)/(2*b.r);
point p=point((lx+rx)/2,0);
circle now;
double r=(a.r-b.r),R=(rx-lx)/2;
ans=r*r*pi;point p2;
for(int i=2;i<=n;i++)
{
if(i%2==0)
{
p=point(p.x,p.y+(rx-lx));
now.o=p;now.r=(rx-lx)/2;
now=inversion(now,point(0,0),lx);
r=now.r;
}
ans+=r*r*pi;
if(r*r*pi*(n-i+1)<eps)
{
printf("%d\n",i);
return;
}
}
}
inline void print()
{
printf("%.5f\n",ans);
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}