[Luogu4525] 【模板】自适应辛普森法1 [自适应Simpson]

Link
https://www.luogu.org/problemnew/show/P4525


卖萌做法
∫ L R c x + d a x + b d x \begin{array}{rcl}\displaystyle\int_L^R\frac{cx+d}{ax+b}dx\end{array} LRax+bcx+ddx
原函数很不好求……整理一下
∫ L R ( c x + d a x + b ) d x = ∫ L R [ c a ( a x + b ) − b c a + d a x + b ] d x = ∫ L R ( c a + d − b c a a x + b ) d x \begin{array}{rcl} \displaystyle\int_L^R\left(\frac{cx+d}{ax+b}\right)dx&=&\displaystyle\int_L^R\left[\frac{\frac{c}{a}(ax+b)-\frac{bc}{a}+d}{ax+b}\right]dx\\\\ &=&\displaystyle\int_L^R\left(\frac{c}{a}+\frac{d-\frac{bc}{a}}{ax+b}\right)dx\\\\ \end{array} LR(ax+bcx+d)dx==LR[ax+bac(ax+b)abc+d]dxLR(ac+ax+bdabc)dx
对于 f ( x ) = c a + d − b c a a x + b \displaystyle{f(x)=\frac{c}{a}+\frac{d-\frac{bc}{a}}{ax+b}} f(x)=ac+ax+bdabc

其原函数 F ( x ) = c a ⋅ x + d − b c a a ⋅ ln ⁡ ∣ a x + b ∣ \displaystyle{F(x)=\frac{c}{a}\cdot x+\frac{d-\frac{bc}{a}}{a}\cdot\ln|ax+b|} F(x)=acx+adabclnax+b
特判 a = 0 a=0 a=0 即可……


三点Simpson公式
直接用抛物线拟合。
∫ L R f ( x ) d x ≈ ∫ L R A x 2 + B x + C = ( R − L ) [ f ( R ) + f ( L ) + 4 f ( L + R 2 ) ] 6 \displaystyle\int_L^Rf(x)dx≈\displaystyle\int_L^RAx^2+Bx+C=\displaystyle\frac{(R-L)\left[f(R)+f(L)+4f(\frac{L+R}{2})\right]}{6} LRf(x)dxLRAx2+Bx+C=6(RL)[f(R)+f(L)+4f(2L+R)]


暴力Simpson法(?)
递归拟合。根据精度需要控制递归终点。
就这样,其实不难。
eps一般设小一点(1e-8到1e-12),如果测出来跑得很慢再慢慢调整?
f ( L , M i d ) + f ( M i d , R ) − f ( L , R ) ≤ ϵ f(L,Mid)+f(Mid,R)-f(L,R)\le\epsilon f(L,Mid)+f(Mid,R)f(L,R)ϵ 则返回 f ( L , M i d ) + f ( M i d , R ) f(L,Mid)+f(Mid,R) f(L,Mid)+f(Mid,R)

#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<set>
#include<ctime>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
double a, b, c, d, l, r;
double eps = 1e-12;
inline double f(const double& x)
{
    return (c*x+d)/(a*x+b);
}
inline double Simpson(const double& L, const double& R)
{
    return (R-L)*(f(R)+f(L)+4.0*f((L+R)/2))/6;
}
double Divide(const double& L, const double& R, const double& ans)
{
    double Mid = (L + R) / 2, l = Simpson(L, Mid), r = Simpson(Mid, R);
    if (fabs(l + r - ans) <= eps) return l + r;
    else return Divide(L, Mid, l) + Divide(Mid, R, r);
}
int main()
{
    scanf("%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &l, &r);
    printf("%.6f", Divide(l, r, Simpson(l, r)));
    return 0;
}

Adaptive Simpson’s method
f a b s ( f ( L , M i d ) + f ( M i d , R ) − f ( L , R ) 15 ) ≤ ϵ \pmb{fabs(}\frac{f(L,Mid)+f(Mid,R)-f(L,R)}{15}\pmb)\le\epsilon fabs(fabs(fabs(15f(L,Mid)+f(Mid,R)f(L,R))))ϵ
Δ = f ( L , M i d ) + f ( M i d , R ) − f ( L , R ) 15 \Delta=\frac{f(L,Mid)+f(Mid,R)-f(L,R)}{15} Δ=15f(L,Mid)+f(Mid,R)f(L,R) ,如果满足上述条件则返回 f ( L ) + f ( R ) + Δ f(L)+f(R)+\Delta f(L)+f(R)+Δ
15 15 15 不能瞎改。

……但是很显然有时候可能会陷入(接近)死循环。
一种简单有效的方法就是限制递归深度……或者当区间积分小到一定程度的时候返回……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值