给出一个N次函数,保证在范围[l,r]内存在一点x,使得[l,x]上单调增,[x,r]上单调减。试求出x的值。
(此题其实当然可以取导用二分做,但是如果有些函数求导很麻烦的话那就用三分)
三分:
此题根据对称性,在(l,r)中间找两个点l',r',若f(l')<f(r')那就取(l',r)否则取(l,r') -----其实可以看成粗糙的取导double f(double x){//秦九昭
double ans=0,k=1;FFor(i,n,0)ans+=k*a[i],k*=x;return ans;}普通三分
double work(double l,r){while(fabs(r-l)>eps){lm=l+(r-l)/3;rm=r-(r-l)/3;if(f(rm)>=f(lm))l=lm;else r=rm;}printf("%.5f",l);
优选法三分:
我看了网上大量博客文章,大多数真心没说到点子上(而且代码也没体现出优化性)实际上就一句话,普通的三分(或者你随意按其他比例缩小范围)都是每次必须取两个点进行计算f(l+len*w),f(r-len*w),但黄金分割法除了第一次取两个点外,以后每次就只需要取一个点就OK了,你说快不快。如图,红点是必须计算的点,灰点因为上一轮已经计算过,所以此轮就不用计算了,这样就实现了每轮只计算一个点的效果 黄金分割数为 (sqrt(5)-1)/2 就不证明了上代码:
#define gor (sqrt(5)-1)/2bool fgl=true,fgr=true;double gold(double l,r){while(fabs(r-l)>eps){double midr=(r-l)*gor+l;double midl=r-(r-l)*gor;if(!fgr)fr=f(midr);if(!fgl)fl=f(midl);if(fl>fr)r=midr,fgr=true,fgl=false;else if(fl