辛普森积分
title: 辛普森积分
categories:
- ICPC
tags:
- null
abbrlink: 48861cf4
date: 2023-11-15 00:00:00
自适应辛普森积分
const double eps=1e-10;
double a,b,c,d,l,r;
double f(double x){ //积分函数
return (c*x+d)/(a*x+b);
}
double simpson(double l,double r){//辛普森公式
return (r-l)*(f(l)+f(r)+4*f((l+r)/2))/6;
}//二次函数特性
double asr(double l,double r,double ans){//自适应
//分段simpson,如果划分足够小,低于误差就可以
auto m=(l+r)/2,a=simpson(l,m),b=simpson(m,r);
if(fabs(a+b-ans)<eps) return ans;
return asr(l,m,a)+asr(m,r,b);
}
int main(){
scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&l,&r);
printf("%.6lf",asr(l,r,simpson(l,r)));
return 0;
}
时间复杂度:$O(log(n/eps))$
tips:要注意保证给的初始区间的积分是收敛的并且不要出现无定义点
$\displaystyle{\int_0^\infty x^{\frac{a}{x}-x}\mathrm{d}x}$
保留至小数点后$5$位。若积分发散,请输出$\text{orz}$。
$|a|\le50$。
Solution:首先把反常积分的发散部分特判,也就是a<0.
对于初始区间,显然不能直接赋值0和无穷大,左端点复制成eps。
考虑右端点,根据a的取值,当x=20的时候代入发现已经远小于eps了故右端点设计为20.
const double eps = 1e-10;
int n, m;
double a;
double f(double x){
return pow(x,(a/x)-x);
}
double sim(double l,double r){
return (r-l)*(f(l)+f(r)+4*f((l+r)/2))/6;
}
double asr(double l,double r,double ans){
auto m=(l+r)/2,a=sim(l,m),b=sim(m,r);
if(fabs(a+b-ans)<eps)return ans;
return asr(l,m,a)+asr(m,r,b);
}
void solve(){
cin>>a;
if(a<0){
cout<<"orz";return ;
}
baoliu(asr(eps,20,sim(eps,20)),5);
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 爱飞鱼的blog!