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.

posted @ 2020-05-21 17:00  chdy  阅读(150)  评论(0编辑  收藏  举报