题解 P3382 【【模板】三分法】
NaCly_Fish · · 题解
看见有很多大佬用求导+二分做的,学过高数都知道,其实求导不难。
那没学过高数的怎么办?
这里提供一种用导数本质来计算的方法。
在看导数的计算之前,我们先想一下斜率的计算。
过
而导数计算的就是过函数某一点切线的斜率。
在函数
当
然后很容易就能得出,函数
不过我们只用求导数的数值解,也就是近似值。所以只需要把
double derivative(double x){
double dx = 1e-10;
double dy = f(x+dx)-f(x);
return dy/dx;
}
其中 f 就是计算函数值的。
对于求导的结果,也可以表示成一个函数变化的快慢(显然),导数值为正表示函数值在增加,导数值为负表示函数在减小。
那么,如果导数值为零,且左边导数值为正,右边导数值为负,那么我们就找到了最小值,
由于这题中保证给定的
另外,这样做还有一个好处:不用计算导函数具体是多少,比本题其它求导做法适用性更广。
参考代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define eps (1e-10)
using namespace std;
double l,r;
int n;
double a[20];
inline double f(double x){
//秦九昭公式求多项式
double u[20];
u[n] = a[n];
for(int i=n-1;i>=0;--i)
u[i] = u[i+1]*x+a[i];
return u[0];
}
double check(double x){
double dx = eps;
double dy = f(x+dx)-f(x);
return dy/dx;
}
int main(){
scanf("%d",&n);
scanf("%lf%lf",&l,&r);
for(int i=0;i<=n;++i)
scanf("%lf",&a[n-i]);
double mid;
while(r-l>eps){
mid = (l+r)/2;
if(check(mid)>0) l = mid;
else r = mid;
}
printf("%.5lf",mid);
return 0;
}