P3382 【模板】三分法
题目
如题,给出一个 \(N\) 次函数,保证在范围 \([l, r]\) 内存在一点 \(x\),使得 \([l, x]\) 上单调增,\([x, r]\) 上单调减。试求出 \(x\) 的值。
思路
本题可以用导数做,(逃
首先,一个 \(N\) 次函数无非就是 一个这样的函数:
\[f(x)=\sum_{i=0}^{n} a_{i}x^{i} \]而根据导数加法法则可以知道,加法函数满足这样的一个性质:
\[(f(x)+g(x)+h(x)+i(x)+...)^{'} = (f^{'}(x)+g^{'}(x)+h^{'}(x)+i^{'}(x)+...) \]因此我们就把他转换成一个求 \(a_{i}x^{i}\) 的导数的问题了。
注意常数的导数为0.
而计算可知,\((a_{i}x^{i})^{'}=a_iix^{i-1}\),所以多项式的函数就变成了
\[f^{'}(x)=\sum_{i=1}^{n} a_iix^{i-1} \]话说为什么要用导数呢?
应为导数的性质告诉我们,一个函数如果区间递增那么导数值要大于等于0!反之就是小于等于0!
可以二分了!
注意,可能会有浮点数误差!
代码
#include
#define int double
using namespace std;
int n,l,r,a[15];
int eps=1e-10,mid;
int derivative(int x){
int result=0;
for(signed i=1;i<=n;i++){
result+=a[i]*i*pow(x,i-1);
}
return result;
}
signed main(){
cin>>n>>l>>r;
for(signed i=n;i>=0;i--){
cin>>a[i];
}
while(r-l>eps){
mid=(l+r)/2;
if(derivative(mid)>0){
l=mid;
}
else{
r=mid;
}
}
printf("%.5lf",mid);
return 0;
}