传送门
思路:
- 很细节的题,要好好读题!
- 首先,正方形可以绕中心旋转,由于正方形落到圆的概率不是很好计算,看怎么才能转化一下。
- 找一个边界值,比如下图中的,正方形再向下一点就会出界。所以只要正方形的中心在蓝色圆里就能够保证正方形落到绿色的大圆里。
![在这里插入图片描述](https://img-blog.csdnimg.cn/086929075b6a488cabcb91151287e4be.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTY3NTA5Nw==,size_16,color_FFFFFF,t_70)
- 这样就把正方形抽象成一个点了。根据红色的直角三角形可以计算出蓝色圆的半径,对两个原始圆求交集就是分子的答案,原始圆的蓝色圆面积就是分母的答案;
- 还有一个细节就是题目里只说了第一个圆足够大,没说奖励圆足够大,要特判一下正方形不能放到奖励圆的情况。
代码:
struct point{
double x,y;
};
double c(point a, double r1, point b, double r2,double t)
{
double d = sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
if (d >= r1+r2)
return 0;
if (r1>r2){
double tmp = r1;
r1 = r2;
r2 = tmp;
}
if(r2 - r1 >= d)
return pi*r1*r1;
double g1=acos((r1*r1+d*d-r2*r2)/(2*r1*d));
double g2=acos((r2*r2+d*d-r1*r1)/(2*r2*d));
return g1*r1*r1 + g2*r2*r2 - r1*d*sin(g1);
}
int main(){
int _=read;
while(_--){
double x1,y1,r1,x2,y2,r2,a;
cin>>r1>>x1>>y1>>r2>>x2>>y2>>a;
if(r2*r2-a*a/4<=0) puts("0.000000");
else{
double R1=sqrt(r1*r1-a*a/4)-a/2;
double R2=sqrt(r2*r2-a*a/4)-a/2;
point t1={x1,y1},t2={x2,y2};
printf("%.6f\n",c(t1,R1,t2,R2,a)/(pi*R1*R1));
}
}
return 0;
}