3074. 自适应辛普森积分

题目链接

3074. 自适应辛普森积分

给定两个整数 \(a,b\),请计算如下积分:

\(\int_a^b \frac{Sin(x)}{x}dx\)

输入格式

共一行,包含两个实数 \(a,b\)

输出格式

输出一个实数,表示结果。

结果保留 \(6\) 位小数。

数据范围

\(1 \le a < b \le 100\)

输入样例:

1.0 2.0

输出样例:

0.659330

解题思路

自适应辛普森积分

辛普森积分主要用来求解任意一个连续函数在一段区间的积分(面积),类似于微积分的定义,即将区间分为很多微小的小段,将区间的高假定为某个值,然后用矩形的面积取代该段不规则的形状的面积,而辛普森积分则是用一个二次函数近似小段的曲线,其用到一个求解一次二次函数某个区间 \([l,r]\) 的面积公式:\(S=(r-l)\times \frac{f(l)+4\times f(mid)+f(r)}{6}\)

而自适应辛普森积分则是先用面积公式求出 \([l,r]\) 内的面积 \(S\),再分别求出左、右半边的面积 \(S_l,S_r\),然后拿 \(S\)\(S_l+S_r\) 进行比较,如果其误差在允许的范围内说明该值可取,否则递归处理左右半边

自适应辛普森积分主要处理一些精度要求不高的问题,而且要求函数低阶

  • 时间复杂度:\((玄学)\)

代码

// Problem: 自适应辛普森积分
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/3077/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const double eps=1e-12;
double l,r;
double f(double x)
{
	return sin(x)/x;
}
double simpson(double l,double r)
{
	double mid=(l+r)/2;
	return (f(l)+f(mid)*4+f(r))/6*(r-l);
}
double asr(double l,double r,double s)
{
	double mid=(l+r)/2;
	double L=simpson(l,mid),R=simpson(mid,r);
	if(fabs(s-L-R)<eps)return L+R;
	return asr(l,mid,L)+asr(mid,r,R);
}
int main()
{
    scanf("%lf%lf",&l,&r);
    printf("%.6lf",asr(l,r,simpson(l,r)));
    return 0;
}
posted @ 2022-11-23 19:29  zyy2001  阅读(91)  评论(0编辑  收藏  举报