公式
F
(
L
,
R
)
=
1
6
(
R
−
L
)
×
(
F
(
L
)
+
F
(
R
)
+
4
F
(
M
i
d
)
)
F(L,R) = \frac{1}{6} (R - L)\times (F(L) + F(R) + 4F(Mid))
F(L,R)=61(R−L)×(F(L)+F(R)+4F(Mid))
考察
A
=
F
(
L
,
M
i
d
)
+
F
(
M
i
d
,
R
)
,
B
=
F
(
L
,
R
)
A = F(L, Mid) + F(Mid, R),B = F(L, R)
A=F(L,Mid)+F(Mid,R),B=F(L,R)
如果
∣
A
−
B
∣
<
=
K
×
e
p
s
|A-B| <= K\times eps
∣A−B∣<=K×eps,结束递归返回
min
A
,
B
+
1
K
∣
A
−
B
∣
\min{A,B} +\frac{1}{K} |A-B|
minA,B+K1∣A−B∣,否则递归为两个子问题。
该公式很好的控制了精度。
如何应用
题目
给定三个同心圆,半径分别为 r 1 r_1 r1, r 2 r_2 r2, r 3 r_3 r3,三个点分别在圆上随机取,求期望面积?
分析
假设我们已经把三个圆的半径排好序了。
乍一看无从下手,可能就直接去推式子了。这里我们应该要冷静,首先由于对称性,我们将第一个点固定在
(
r
1
,
0
)
(r_1,0)
(r1,0)处,第二个点在圆上跑,假设为
(
r
2
c
o
s
θ
,
r
2
s
i
n
θ
)
(r_2cos\theta ,r_2sin\theta )
(r2cosθ,r2sinθ), 我们可以手动积分出面积
S
=
r
3
l
e
n
π
(
c
o
s
β
+
β
s
i
n
β
)
S = \frac{{r}_{3}len}{\pi}(cos\beta +\beta sin\beta)
S=πr3len(cosβ+βsinβ),其中
l
e
n
len
len是随机的点与固定点的距离,
s
i
n
β
=
∣
r
1
r
2
s
i
n
θ
r
3
l
e
n
∣
sin\beta = |\frac{r_1r_2sin\theta}{r_3len}|
sinβ=∣r3lenr1r2sinθ∣,于是我们就可以套用simpson积分求解了。
代码
// An highlighted block
#include <iostream>
#include <cmath>
using namespace std;
const double pai = acos(-1) , eps = 1e-5;
int r1,r2,r3;
double Power(double x){
return x * x;
}
double F(double x){
double len = sqrt(Power(r2 * cos(x) - r1) + Power(r2 * sin(x)));
double b = len < eps ? 0 : asin(r1 * r2 * fabs(sin(x)) / (len * r3));
double ret = r3 * len * (cos(b) + b * sin(b)) / pai;
return ret;
}
double simpson(double l, double r){
double mid = l + (r - l) / 2;
return (F(l) + 4 * F(mid) + F(r)) * (r - l) / 6;
}
double cal(double l, double r){
double mid = l + (r - l) / 2;
double L = simpson(l , mid) , R = simpson(mid , r) , A = simpson(l , r);
if(fabs(L + R - A) < 5 * eps)
return L + R + fabs(L + R - A) / 5.0;
return cal(l , mid) + cal(mid , r);
}
void solve(){
scanf("%d%d%d", &r1, &r2, &r3);
if(r1 > r2)
swap(r1, r2);
if(r2 > r3)
swap(r2 , r3);
if(r1 > r2)
swap(r1 , r2);
double ans = cal(0 , 2 * pai) / (2 * pai);
printf("%.1f\n" , ans);
}
int main(){
int T;
scanf("%d" , &T);
while(T --)
solve();
return 0;
}