1. 程式人生 > >【luogu 3382】【模板】三分法

【luogu 3382】【模板】三分法

include 表示 時空 return 三分 %d color upload printf

題目描述

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

輸入輸出格式

輸入格式:

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

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

輸出格式:

輸出為一行,包含一個實數,即為x的值。四舍五入保留5位小數。

輸入輸出樣例

輸入樣例#1:
3 -0.9981 0.5
1 -3 -3 1
輸出樣例#1:
-0.41421

說明

時空限制:50ms,128M

數據規模:

對於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。

題解:

裸三分。

在[L,R]中,

取a=(R-L)/3+L,b=(R-L)/3*2+L。

如果f(a)>f(b)

則答案在[L,b]裏(如果在[b, R]裏,則[a, b]段遞增),

如果f(a)<f(b)

則答案在[a,R]裏(如果在[L, a]裏,則[a, b]段遞減),

遞歸或循環即可。

 1 #include<cstdio>
 2
#include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 double l,r,xs[23];int n; 8 double f(double x){ 9 double ans=0; 10 for(int i=1;i<=n;i++){ 11 double tmp=xs[i]; 12 for(int j=1;j<=n-i+1
;j++) tmp*=x; 13 ans+=tmp; 14 } 15 return ans+xs[n+1]; 16 } 17 int main(){ 18 scanf("%d",&n); 19 scanf("%lf%lf",&l,&r); 20 for(int i=1;i<=n+1;i++) scanf("%lf",&xs[i]); 21 double lx=l,rx=r; 22 while(abs(lx-rx)>0.000001){ 23 double x1=(rx-lx)/3+lx,x2=(rx-lx)/3*2+lx; 24 if(f(x1)>f(x2)) rx=x2; 25 else lx=x1; 26 } 27 printf("%.5f\n",lx); 28 return 0; 29 }

【luogu 3382】【模板】三分法