题解 P4526 【【模板】自适应辛普森法2】
Great_Influence
2018-05-06 20:32:13
简单积分。。。
不要被式子的无穷大吓到了。将函数图像画出来,可以轻易地发现,当大于一定值时,函数趋于0,对答案基本没有贡献。这个值随着$a$增大增大,然而当$a=50$时,这个值不超过8,为了求稳就可以从$eps$积分到$20$。为什么不从0开始?因为当$a=0$时,$f(0)=1$而不是$0$,所以计算会出现错误。避免特殊点对积分产生影响也是辛普森自适应积分的一个重点。记得$eps$开小一点,最好开小$4$个数量级。
什么时候无解?画一下图可以发现,当$a<0$时,$\lim\limits_{x\to 0} f(x)\to+\infty$,函数不收敛。直接判掉即可。
代码:
```cpp
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#define For(i,a,b) for(i=(a),i##end=(b);i<=i##end;++i)
#define Forward(i,a,b) for(i=(a),i##end=(b);i>=i##end;--i)
#define Rep(i,a,b) for(register int i=(a),i##end=(b);i<=i##end;++i)
#define Repe(i,a,b) for(register int i=(a),i##end=(b);i>=i##end;--i)
#define Chkmax(a,b) a=a>b?a:b
#define Chkmin(a,b) a=a<b?a:b
using namespace std;
template<typename T>inline void read(T &x){
T s=0,f=1;char k=getchar();
while(!isdigit(k)&&k^'-')k=getchar();
if(!isdigit(k)){f=-1;k=getchar();}
while(isdigit(k)){s=s*10+(k^48);k=getchar();}
x=s*f;
}
void file(void){
#ifndef ONLINE_JUDGE
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
#endif
}
static double a;
const double eps=1e-9;
inline double f(double x){return pow(x,a/x-x);}
inline double calc(double l,double r)
{return (r-l)*(f(l)+f(r)+4.0*f((l+r)/2.0))/6.0;}
inline double simpson(double L,double R,double ans)
{
double mid=(L+R)/2.0,lans=calc(L,mid),rans=calc(mid,R);
if(fabs(lans+rans-ans)<=eps)return ans;
return simpson(L,mid,lans)+simpson(mid,R,rans);
}
int main(void){
file();
scanf("%lf",&a);
if(a<0)return puts("orz"),0;
printf("%.5lf\n",simpson(eps,20,calc(eps,20)));
return 0;
}
```