1. 程式人生 > 其它 >P3382 【模板】三分法

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;
}