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]dx∫LR(ac+ax+bd−abc)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+bd−abc
其原函数
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)=ac⋅x+ad−abc⋅ln∣ax+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)dx≈∫LRAx2+Bx+C=6(R−L)[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 不能瞎改。
……但是很显然有时候可能会陷入(接近)死循环。
一种简单有效的方法就是限制递归深度……或者当区间积分小到一定程度的时候返回……