洛谷 P3382 【模板】三分法

題目描述

如題,給出一個\(N\)次函數,保證在範圍\([l,r]\)內存在一點\(x\),使得\([l,x]\)上單調增,\([x,r]\)上單調減。試求出\(x\)的值。函數

輸入輸出格式

輸入格式:學習

第一行一次包含一個正整數\(N\)和兩個實數\(l、r\),含義如題目描述所示。spa

第二行包含\(N+1\)個實數,從高到低依次表示該\(N\)次函數各項的係數。code

輸出格式:blog

輸出爲一行,包含一個實數,即爲\(x\)的值。四捨五入保留\(5\)位小數。ip

輸入輸出樣例

輸入樣例#1:內存

3 -0.9981 0.5
1 -3 -3 1

輸出樣例#1:it

-0.41421

說明

時空限制:\(50ms,128M\)io

數據規模:模板

對於\(100\%\)的數據:\(7<=N<=13\)

樣例說明:

如圖所示,紅色段即爲該函數\(f(x)=x^3-3x^2-3x+1\)在區間\([-0.9981,0.5]\)上的圖像。

\(x=-0.41421\)時圖像位於最高點,故此時函數在\([l,x]\)上單調增,\([x,r]\)上單調減,故\(x=-0.41421\),輸出\(-0.41421\)

(Tip.l&r\(的範圍並非很是大\)ww$不會超過一位數)

思路:其實以前作過這個題目,可是用的不是三分法,因此今天看知識體系,恰好發現本身不會三分法,就去學習了一下順便回顧了這道模板題,三分的思路就是,先取\(l\)\(r\)的中間點\(mid\),再取\(mid\)\(r\)的中間值\(mmid\),而後比較\(f(mid)\)\(f(mmid)\),其中\(f(x)\)表示把x代入函數後的值爲多少,若是\(f(mid)>f(mmid)\),說明要找的點在\(mmid\)的左邊,因此就讓\(r=mmid\),繼續三分,反之,讓\(l=mid\),繼續三分,最後的\(l\)\(r\)必定會愈來愈接近要找的點,r和l的差在偏差容許範圍內時,就找完了。

代碼:

#include<cstdio>
#include<algorithm>
#define dl double
#define maxn 15
using namespace std;
const dl eps=1e-7;
int n;
dl a[maxn],l,r,p;
inline dl js(dl x) {
  dl res=a[0];
  for(int i=1;i<=n;++i) {
    dl tmp=a[i];
    for(int j=1;j<=i;++j) 
      tmp*=x;
    res+=tmp;
  }
  return res;
}
int main() {
  scanf("%d%lf%lf",&n,&l,&r);
  for(int i=n;i>=0;--i) {
    scanf("%lf",&p);
    a[i]=p;
  } 
  while(l+eps<r) {
    dl mid=(l+r)/2;
    dl mmid=(mid+r)/2;
    if(js(mid)>js(mmid)) r=mmid;
    else l=mid;
  }
  dl ans=js(l)>js(r)?l:r;
  printf("%0.5lf\n",r);
  return 0;
}
相關文章
相關標籤/搜索