hdu 6158(数学定理)

The Designer 笛卡尔定理 递推

http://acm.hdu.edu.cn/showproblem.php?pid=6158

阳哥原文:https://swustacm.cn/?p=426

 

一个大圆O1O1和三个小圆O2O3O4O2、O3、O4内切,三个小圆相互外切,他们的半径满足如下等式:
(1r2+1r3+1r41r1)2=2(1r21+1r22+1r23+1r24)(1r2+1r3+1r4−1r1)2=2(1r12+1r22+1r32+1r42)

hdu 6158(数学定理)_第1张图片

计算有标号圆的面积。
设大圆半径为rara,左边的圆半径为rbrb。则r1=rarbr1=ra−rb
只看上半部分的圆,对圆重新编号为1、2、3、……
r1=rarbr1=ra−rb
设第kk个圆的半径为rkrk,根据笛卡尔定理有如下等式
(1rk+1rk+1+1rb1ra)2=2(1r2k+1r2k+1+1r2b+1r2a)(1rk+1rk+1+1rb−1ra)2=2(1rk2+1rk+12+1rb2+1ra2)
同时也有
(1rk+1rk1+1rb1ra)2=2(1r2k+1r2k1+1r2b+1r2a)(1rk+1rk−1+1rb−1ra)2=2(1rk2+1rk−12+1rb2+1ra2)
上下两式相减,得到
(1rk+11rk1)(2rk+1rk+1+1rk1+2rb2ra)=2(1r2k+11r2k1)(1rk+1−1rk−1)(2rk+1rk+1+1rk−1+2rb−2ra)=2(1rk+12−1rk−12)
将右边展开,得到
(1rk+11rk1)(2rk+1rk+1+1rk1+2rb2ra)=2(1rk+11rk1)(1rk+1+1rk1)(1rk+1−1rk−1)(2rk+1rk+1+1rk−1+2rb−2ra)=2(1rk+1−1rk−1)(1rk+1+1rk−1)
两边同时消去(1rk+11rk1)(1rk+1−1rk−1),得到
2rk+1rk+1+1rk1+2rb2ra=2rk+1+2rk12rk+1rk+1+1rk−1+2rb−2ra=2rk+1+2rk−1
合并同类项,得到
2rk+2rb2ra=1rk+1+1rk12rk+2rb−2ra=1rk+1+1rk−1
移项得到
1rk+1=2rk+2rb2ra1rk11rk+1=2rk+2rb−2ra−1rk−1
这是一个关于rkrk的递推式,知道前两项就能递推出后一项。
但是现在只知道r1rarbr1、ra、rb,还不知道r2r2,无法进行递推。
根据笛卡尔定理有
(1r1+1r2+1rb1ra)2=2(1r21+1r22+1r2b+1r2a)(1r1+1r2+1rb−1ra)2=2(1r12+1r22+1rb2+1ra2)
将其左右展开有
1r22+2×1r2(1r1+1rb1ra)=2×1r22+2(1r21+1r2b+1r2a)1r22+2×1r2(1r1+1rb−1ra)=2×1r22+2(1r12+1rb2+1ra2)
移项合并同类型,得到如下
1r222(1r1+1rb1ra)1r2+2(1r21+1r2b+1r2a)=01r22−2(1r1+1rb−1ra)1r2+2(1r12+1rb2+1ra2)=0
1r21r2看作未知量,根据实际情况,方程的两个根应该相同,所以根据韦达定理有
1r2+1r2=2(1r1+1rb1ra)1r2+1r2=2(1r1+1rb−1ra)

1r2=1r1+1rb1ra1r2=1r1+1rb−1ra
已经求得r1r1r2r2,可以递推了。

代码:

#include
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;
}



你可能感兴趣的:(hdu 6158(数学定理))