Simpson积分应用

公式

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(RL)×(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 AB<=K×eps,结束递归返回 min ⁡ A , B + 1 K ∣ A − B ∣ \min{A,B} +\frac{1}{K} |A-B| minA,B+K1AB,否则递归为两个子问题。
该公式很好的控制了精度。

如何应用

题目

给定三个同心圆,半径分别为 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值