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 <bits/stdc++.h>
#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;
}
posted @ 2022-02-19 10:29  蒟蒻xiezheyuan  阅读(23)  评论(0编辑  收藏  举报