【数学】三分法

Definition

当一个函数f(x)满足在区间在区间[l,r]内有且仅有一个x  [l,r] , s.t.  f(x)[l,x]内单调严格递增,在[x,r]内单调严格递减,则说f(x)[l,r]内是一个单峰函数,求出单峰点x的算法为三分法。

Solution

考虑对一个区间[l,r],取三等分点,记做midlmidr。不妨设midl < midr,则若f(midl)  f(midr),则单峰点一定在区间[midlr]范围内。反之单峰点一定在区间[l,midr]范围内。

证明:

首先设f(midl) < f(midr)

以下说明midl一定不在单峰点右侧。

midl在单峰点右侧,则 x0  (midl,r],都有f(x0) < f(x)。因为midr > midlf(midr) > f(midl),于是产生矛盾。故可说明midl一定不再单峰点右侧。

f(midl) > f(midr)时,证明同上。

再设f(midl) = f(midr)

以下说明单峰点一定在[midl,midr]之间

假设midlmidr同在单峰点一侧,则f(x)在区间[midl,midr]上严格单调,而f(midl) = f(midr),产生矛盾。于是单峰点一定在[midl,midr]之间。

证毕

于是在[l,r]内取两个三等分点(在代码中使用黄金分割点),比较两点函数值大小,对函数值较小的一侧缩小区间即可。

Example

传送门

Description

给出一个N次函数,保证在范围[l,r]内存在一点x,使得[l,x]上单调增,[x,r]上单调减。试求出x的值。

Input

第一行一次包含一个正整数N和两个实数l,r,含义如题目描述所示。

第二行包含N+1个实数,从高到低依次表示该N次函数各项的系数。

Output

输出为一行,包含一个实数,即为x的值。四舍五入保留5位小数。

Hintt

forall:

7  n  13 , |Ai| <10。其中|Ai|为系数

Solution

板子题要啥solution

Code

#include<cmath>
#include<cstdio>
#define rg register
#define ci const int
#define cl const long long

typedef long double ldb;
typedef long long int ll;

template <typename T>
inline void qr(T &x) {
	rg char ch=getchar(),lst=' ';
	while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
	while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	if(lst == '-') x=-x;
}

namespace IO {
	char buf[120];
}

template <typename T>
inline void qw(T x,const char aft,const bool pt) {
	if(x < 0) {x=-x,putchar('-');}
	rg int top=0;
	do {IO::buf[++top]=x%10+'0';} while(x/=10);
	while(top) putchar(IO::buf[top--]);
	if(pt) putchar(aft);
}

inline void readldb(long double &x) {
	double _temp;
	scanf("%lf",&_temp);
	x=_temp;
}

inline void printldb(const long double &x) {
	double _ret=x;
	printf("%.5lf\n",_ret);
}

const int maxn = 20;
const long double eps = 1e-10l;
const long double mul = 0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374l;

int n;
ldb MU[maxn];

ldb ask(ldb);

int main() {
	qr(n);
	ldb l,r;readldb(l);readldb(r);
	for(rg int i=0;i<=n;++i) readldb(MU[i]);
	while((r-l) >= eps) {
		ldb midl=r-(r-l)*mul,midr=l+(r-l)*mul;
		ldb ansl=ask(midl),ansr=ask(midr);
		if(ansl >= ansr) r=midr-eps;
		else l=midl+eps;
	}
	printldb(l);
	return 0;
}

ldb ask(ldb x) {
	ldb _ret=0,_dx=1;
	for(rg int i=n;~i;--i) _ret+=MU[i]*_dx,_dx*=x;
	return _ret;
}

Summary

当且仅当在单峰点两侧严格单调才能作为单峰函数处理

posted @   一扶苏一  阅读(808)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示