题解 P4526 【【模板】自适应辛普森法2】

Great_Influence

2018-05-06 20:32:13

Solution

简单积分。。。 不要被式子的无穷大吓到了。将函数图像画出来,可以轻易地发现,当大于一定值时,函数趋于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; } ```