P4525 【模板】自适应辛普森法1

题目描述

试计算积分$$\int_{R}^{L} \frac{cx+d}{ax+b}dx$$

结果保留至小数点后 $6$位

数据保证计算过程中分母不为 $0$ 且积分能够收敛。

输入格式

一行,包含 $6$ 个实数 $a,b,c,d,L,R$。

输出格式

一行,积分值,保留至小数点后 $6$ 位。

样例数据

输入

1 2 3 4 5 6

输出

2.732937

分析

注意特判$a=0$的情况

法一(数学)

$$\int_{R}^{L} \frac{cx+d}{ax+b}dx \\=\int_{R}^{L}\frac{c}{a} \times \frac{\frac{ad-bc}{a}}{ax+b}dx\\=\int_{R}^{L}\frac{c}{a} dx \times \int_{R}^{L}\frac{\frac{ad-bc}{a}}{ax+b}dx\\=\frac{c}{a}x+\frac{ad-bc}{a}\times \frac{1}{a}ln\left | ax+b\right |+C\\=\frac{ad-bc}{a^2}ln\left | ax+b\right |+C$$

法二(自适应辛普森算法)

当前段直接代入公式求积分,再将当前段从中点分割成两段,把这两段再直接代入公式求积分。如果当前段的积分和分割成两段后的积分之和相差很小的话,就可以认为当前段和二次函数很相似了,不用再递归分割了,代入公式计算,否则递归分割

 

代码

数学

#include <bits/stdc++.h>

#define Space putchar(' ')
#define Enter puts("")
#define MAXN 100010
#define int long long

using namespace std;

typedef long long ll;
typedef double Db;

inline ll Read()
{
    ll Ans = 0;
    char Ch = getchar() , Las = ' ';
    while(!isdigit(Ch))
    {
        Las = Ch;
        Ch = getchar();
    }
    while(isdigit(Ch))
    {
        Ans = (Ans << 3) + (Ans << 1) + Ch - '0';
        Ch = getchar();
    }
    if(Las == '-')
        Ans = -Ans;
    return Ans;
}

inline void Write(ll x)
{
    if(x < 0)
    {
        x = -x;
        putchar('-');
    }
    if(x >= 10)
        Write(x / 10);
    putchar(x % 10 + '0');
}

Db a , b , c , d , L , R;

inline Db F(Db x)
{
    return ((a * d - b * c) / (a * a)) * log(fabs(a * x + b)) + (c / a) * x;
}

inline Db F2(Db x)
{
    return c * x * x / (2 * b) + d * x / b;
}
signed main()
{
    scanf("%lf%lf%lf%lf%lf%lf" , &a , &b , &c , &d , &L , &R);
    if(a != 0)
        printf("%.6lf" , F(R) - F(L));
    else
        printf("%.6lf" , F2(R) - F2(L));
    return 0;
}

自适应辛普森

#include <bits/stdc++.h>

#define Space putchar(' ')
#define Enter puts("")
#define MAXN 100010
#define int long long

using namespace std;

typedef long long ll;
typedef double Db;

inline ll Read() {
    ll Ans = 0;
    char Ch = getchar() , Las = ' ';
    while(!isdigit(Ch)) {
        Las = Ch;
        Ch = getchar();
    }
    while(isdigit(Ch)) {
        Ans = (Ans << 3) + (Ans << 1) + Ch - '0';
        Ch = getchar();
    }
    if(Las == '-')
        Ans = -Ans;
    return Ans;
}

inline void Write(ll x) {
    if(x < 0) {
        x = -x;
        putchar('-');
    }
    if(x >= 10)
        Write(x / 10);
    putchar(x % 10 + '0');
}

Db a , b , c , d , L , R;
Db eps = 0.0000001;

inline double f(double x) {
    return (c*x+d)/(a*x+b);
}

double simpson(double l, double r) {
    double mid = (l + r) / 2;
    return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6;
}
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);
}
signed main() {
    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;
}

 

 

posted @ 2021-06-05 21:37  Tenderfoot  阅读(58)  评论(0编辑  收藏  举报