luogu P4525 自适应辛普森法1
LINK:自适应辛普森法1
观察题目 这个东西 凭借我们的数学知识应该是化简不了的。
可以直接认为是一个函数 求定积分直接使用辛普森就行辣.
一种写法:
double a,b,c,d;
double f(double x){
return (c*x+d)/(a*x+b);
}
//区间[a,b]上的辛普森值
double simpson(double a,double b){
double c=a+(b-a)/2;
return (f(a)+4*f(c)+f(b))*(b-a)/6;
}
//区间[a,b]上的积分,精度限制为eps,已知整个区间的辛普森值A
double asr(double a,double b,double eps,double A){
double c=a+(b-a)/2;
double L=simpson(a,c),R=simpson(c,b);
if(fabs(L+R-A)<=15*eps) return L+R+(L+R-A)/15;
else return asr(a,c,eps/2,L)+asr(c,b,eps/2,R);
}
const double eps=1e-7;
int main(){
double l,r;
scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&l,&r);
printf("%.6f\n",asr(l,r,eps,simpson(l,r)));
return 0;
}
这种 写法比较常见 精度也比较稳 值得注意的是 exp每次需要/2 然后积分的时候要乘上15.
最后注意 要加上辛普森余项 (L-R-A)/15. (15是人类研究出来的结果 不要问 问就是前沿哥
一种比较偷懒的写法:
const int MAXN=1010;
db a,b,c,d,L,R;
inline db f(db x){return (c*x+d)/(a*x+b);}
inline db simpson(db l,db r)
{
db mid=(l+r)/2;
return (r-l)*(f(l)+4*f(mid)+f(r))/6;
}
inline db jf(db l,db r,db ans)
{
db mid=(l+r)/2;
db L=simpson(l,mid),R=simpson(mid,r);
if(fabs(L+R-ans)<EPS)return L+R;
return jf(l,mid,L)+jf(mid,r,R);
}
int main()
{
freopen("1.in","r",stdin);
gi(a);gi(b);gi(c);gi(d);gi(L);gi(R);
printf("%.6lf",jf(L,R,simpson(L,R)));
}
EPS开小点直接积分 不过要注意时间 问题 时间不够就开大eps.