先把内外两个初始的圆反演成两条平行直线
然后里面的圆肯定都是这两条平行直线之间相切的圆反演回去的圆啦。
直接一个一个的算就好了。题目给的N很大,但是当反演回去的圆的面积小到一定程度可忽略,跳出循环就好。。
自己写的东西一开始常数超级大而且好像会RE之类的。。
也是调了一年的题。。最后还是借鉴了网上的写法。。。计算几何好难啊。。。
代码:
#include <bits/stdc++.h>
using namespace std;
#define sq(x) ((x)*(x))
double refr;
#define reflect(x) (sq(refr)/(x))
const double PI = acos(-1.0);
const double eps = PI*1e-13;
int t, N;
double R[2];
int tot = 0;
double dlt, length, high, tlen, r, area_, area;
int main() {
scanf("%d", &t);
while (t--) {
scanf("%lf%lf%d", &R[0], &R[1], &N);
if (R[0] > R[1]) swap(R[0], R[1]);
refr = 2. * R[1];
dlt = (reflect(2*R[0]) - reflect(2*R[1]))/2.;
length = sq(refr + dlt);
high = 0.;
area = sq(R[1] - R[0]); --N;
tlen, r, area_;
while (N) {
high += dlt*2;
tlen = sqrt(length+sq(high));
r = (reflect(tlen-dlt)-reflect(tlen+dlt))/2.;
area_ = sq(r);
if (area_ < eps) break;
area += area_; --N;
if (!N) break;
area += area_; --N;
}
printf("%.5f\n", area * PI);
}
}