题解 P4526 【【模板】自适应辛普森法2】

· · 题解

关于正解,比较详细的整理在这儿\color{red}{Link}

此处主要说一种能够水过去的方法。我们发现eps1e-5的,在朴素的Adaptive-Simpson中,我们要不断取half——但由于本题精度要求不高,所以直接取一个比较小的精度,比如5e-8。然后我们不断运用Simpson公式来取舍区间,即,我们用一种“高仿”的方式来进行Adaptive-Simpson:


inline double do_divide(double l, double r, double Lans){
    double Lv, Rv, v, t ; Lv = Simp_calc(l, mid), Rv = Simp_calc(mid, r), v = Lans ;
    if (fabs(t = (Lv + Rv - v)) <= Eps) return Lv + Rv ; return do_divide(l, mid, Lv) + do_divide(mid, r, Rv) ;
}

它虽然既没有折半传递,又没有精度控制,但是

它能过

……真是无可辩驳啊233

#define mid (l + r) / 2
using namespace std ;
const double Eps = 5e-8 ;
double Ans, A, B, C, D, L, R ;
inline double F(double x){
    return pow(x, A / x - x) ;
}
inline double Simp_calc(double l, double r){
    return (r - l) / 6 * (F(l) + F(r) + 4 * F(mid)) ;
}
inline double do_divide(double l, double r, double Lans){
    double Lv, Rv, v, t ; Lv = Simp_calc(l, mid), Rv = Simp_calc(mid, r), v = Lans ;
    if (fabs(t = (Lv + Rv - v)) <= Eps) return Lv + Rv ; return do_divide(l, mid, Lv) + do_divide(mid, r, Rv) ;
}

int main(){
    scanf("%lf", &A) ; L = Eps, R = 23.3 ;
    if (A < 0) { puts("orz"), cout << endl ; return 0 ;}
    Ans = do_divide(L, R, Simp_calc(L, R)) ; printf("%.5lf", Ans) ; return 0 ; 
}

不过还是建议改一改数据,稍微卡一卡精度…嗝…