http://acm.hdu.edu.cn/showproblem.php?pid=6158
阳哥原文:https://swustacm.cn/?p=426
一个大圆O1和三个小圆O2、O3、O4内切,三个小圆相互外切,他们的半径满足如下等式:
(1r2+1r3+1r4−1r1)2=2(1r21+1r22+1r23+1r24)
计算有标号圆的面积。
设大圆半径为ra,左边的圆半径为rb。则r1=ra−rb
只看上半部分的圆,对圆重新编号为1、2、3、……
r1=ra−rb
设第k个圆的半径为rk,根据笛卡尔定理有如下等式
(1rk+1rk+1+1rb−1ra)2=2(1r2k+1r2k+1+1r2b+1r2a)
同时也有
(1rk+1rk−1+1rb−1ra)2=2(1r2k+1r2k−1+1r2b+1r2a)
上下两式相减,得到
(1rk+1−1rk−1)(2rk+1rk+1+1rk−1+2rb−2ra)=2(1r2k+1−1r2k−1)
将右边展开,得到
(1rk+1−1rk−1)(2rk+1rk+1+1rk−1+2rb−2ra)=2(1rk+1−1rk−1)(1rk+1+1rk−1)
两边同时消去(1rk+1−1rk−1),得到
2rk+1rk+1+1rk−1+2rb−2ra=2rk+1+2rk−1
合并同类项,得到
2rk+2rb−2ra=1rk+1+1rk−1
移项得到
1rk+1=2rk+2rb−2ra−1rk−1
这是一个关于rk的递推式,知道前两项就能递推出后一项。
但是现在只知道r1、ra、rb,还不知道r2,无法进行递推。
根据笛卡尔定理有
(1r1+1r2+1rb−1ra)2=2(1r21+1r22+1r2b+1r2a)
将其左右展开有
1r22+2×1r2(1r1+1rb−1ra)=2×1r22+2(1r21+1r2b+1r2a)
移项合并同类型,得到如下
1r22−2(1r1+1rb−1ra)1r2+2(1r21+1r2b+1r2a)=0
将1r2看作未知量,根据实际情况,方程的两个根应该相同,所以根据韦达定理有
1r2+1r2=2(1r1+1rb−1ra)
则
1r2=1r1+1rb−1ra
已经求得r1和r2,可以递推了。
代码:
#include<bits/stdc++.h> using namespace std; const double esp=1e-13; const double PI=acos(-1.0); int main() { int T; scanf("%d",&T); while(T--) { int ra,rb,n; scanf("%d%d%d",&ra,&rb,&n); if(ra<rb) swap(ra,rb); double r1=ra-rb; double k1=1.0/ra,k2=1.0/rb,k3=1.0/r1; double k4=k3+k2-k1; double ans=r1*r1; n--; for(int i=1;i<=n;i+=2) { double r2=1.0/k4; if(r2*r2<esp) break; ans+=r2*r2; if((i+1)<=n) ans+=r2*r2; double k5=2*(k4+k2-k1)-k3; k3=k4,k4=k5; } printf("%.5f\n",ans*PI); } return 0; }