抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

并没想打算开篇小小结,只是随便写写(感觉开小小结的成本太高了啊……)

感觉还是挺妙的。以前听 zyy 大佬 讲课的时候说过,函数的积分用二次函数拟合一下。

加入我们要算 lrF(x)dx\int_l^r F(x)\mathrm{d}x,我们用二次函数f(x)=ax2+bx+cf(x)=ax^2+bx+c 来拟合。

我们发现:

lrf(x)dx=a3r3+b2r2+cra3l3b2l2cl=a3(rl)(r2+l2+lr)+b2(rl)(r+l)+c(rl)=rl6(2ar2+2al2+2alr+3br+3bl+6c)=rl6(ar2+br+c+al2+bl+c+ar2+al2+2alr+2br+2bl+4c)=rl6(f(l)+f(r)+a(l+r)2+2b(l+r)+4c)=rl6(f(l)+f(r)+4(a(l+r2)2+b(l+r2)+c))=rl6(f(l)+f(r)+4f(l+r2))\begin{aligned} \int_l^r f(x)\mathrm{d}x&=\frac{a}{3}r^3+\frac{b}{2}r^2+cr-\frac{a}{3}l^3-\frac{b}{2}l^2-cl\\ &=\frac{a}{3}\left(r-l\right)\left(r^2+l^2+lr\right)+\frac{b}{2}\left(r-l\right)\left(r+l\right)+c\left(r-l\right)\\ &=\frac{r-l}{6}\left(2ar^2+2al^2+2alr+3br+3bl+6c\right)\\ &=\frac{r-l}{6}\left(ar^2+br+c+al^2+bl+c+ar^2+al^2+2alr+2br+2bl+4c\right)\\ &=\frac{r-l}{6}\left(f(l)+f(r)+a(l+r)^2+2b(l+r)+4c\right)\\ &=\frac{r-l}{6}\left(f(l)+f(r)+4\left(a\left(\frac{l+r}{2}\right)^2+b\left(\frac{l+r}{2}\right)+c\right)\right)\\ &=\frac{r-l}{6}\left(f(l)+f(r)+4f\left(\frac{l+r}{2}\right)\right) \end{aligned}

于是我们有:

lrF(x)dxrl6(F(l)+F(r)+4F(l+r2))\int_l^r F(x)\mathrm{d}x\approx\frac{r-l}{6}\left(F(l)+F(r)+4F\left(\frac{l+r}{2}\right)\right)

然后就可以拟合辣!

1
2
3
4
inline double simpson(double l, double r)
{
return (F(l) + F(r) + 4 * F((l + r) / 2)) * (r - l) / 6;
}

然而就是要么 WA(炸精度)要么 T……

有一种叫自适应辛普森的方法解决这个问题,我们用辛普森计算 lrF(x)dx\int_l^rF(x)\mathrm{d}xl(l+r)/2F(x)dx\int_l^{(l+r)/2}F(x)\mathrm{d}x(l+r)/2rF(x)dx\int_{(l+r)/2}^rF(x)\mathrm{d}x 的值,如果lrF(x)dx(l(l+r)/2F(x)dx+(l+r)/2rF(x)dx)eps\left|\int_l^rF(x)\mathrm{d}x-\left(\int_l^{(l+r)/2}F(x)\mathrm{d}x+\int_{(l+r)/2}^rF(x)\mathrm{d}x\right)\right|\le \mathrm{eps},那么直接返回值,否则递归下去算。

upd:忽然发现我学了个假的 simpson。其实eps 应该是相对误差,所以每次递归下去时 eps\mathrm{eps} 都应该除 22。听说最后判定时应该是15eps\le 15\cdot \mathrm{eps},虽然我并不知道是为什么。 话说这和 eps 乘上 15 有什么区别吗

这样复杂度就是 O(玄学)\mathcal{O}\left(\text{玄学}\right),交之前洗把脸就行了。

1
2
3
4
5
6
7
8
inline double asr(double l, double r, double ans, double eps)
{
double mid = (l + r) * .5;
double ll = simpson(l, mid), rr = simpson(mid, r);
if(fabs(ll + rr - ans) < 15 * eps)
return ll + rr;
return asr(l, mid, ll, eps * .5) + asr(mid, r, rr, eps * .5);
}

评论