[ 三分法 ] 单峰(单谷)函数 三分找极点

https://www.luogu.org/problemnew/show/P3382
题目描述
如题,给出一个N次函数,保证在范围[l,r]内存在一点x,使得[l,x]上单调增,[x,r]上单调减。试求出x的值。

输入输出格式
输入格式:
第一行一次包含一个正整数N和两个实数l、r,含义如题目描述所示。

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

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

原理简单,且适用于所有在定义域中单调性只改变一次的函数,
就是比较定义域中的两个三等分点的映射值,若左边的三等分点比较大,则将右边界右移,对于左边界同理,最终不断逼近得到单峰的位置。
三等分点怎么求,左边界右边三分之一的区间长度和右边界左边三分之一的区间长度。

三分法

#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int, int> P;

const int maxn = 100000 + 5 ;
const int INF = 0x3f3f3f3f ;
const int mod = 9901 ;
const double eps = 1e-6;

int n;
double a[25];

double fun(double x) {
	double res = 0;
	for(int i = 0; i <= n; i++)
		res = res * x + a[i];
	return res;
}

signed main() {
	// fastio;
	double l, r, midl, midr;
	cin >> n >> l >> r;

	for(int i = 0; i <= n; i++)
		cin >> a[i];

	while(r - l > eps) {
		double d = (r - l) / 3.0;
		midl = (l + d), midr = (r - d);

		if(fun(midl) > fun(midr))
			r = midr;
		else
			l = midl;
	}
	printf("%.5lf\n", l);
	return 0;
}

求导二分

当然 由于这道题是多项式给的好 所以 幂函数求导 然后二分 求导是0的点必然对于这个单峰函数来说是极点

导数的函数对应的值表示每一点的切线斜率,所以当该点的导数值大于0则单调增,小于零则单调减,所以只需判断是否大于零即可。
缺点,如果换一道题不是多项式函数的话就不能用这个求单峰了。

#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int, int> P;

const int maxn = 100000 + 5 ;
const int INF = 0x3f3f3f3f ;
const int mod = 9901 ;
const double eps = 1e-6;

int n;
double a[25];

double fun(double x) {
	double res = 0;
	for(int i = 0; i < n; i++) // 常数项 消失 求导完 
		res = res * x + a[i];
	return res;
}

signed main() {
	// fastio;
	double l, r, midl, midr;
	cin >> n >> l >> r;

	for(int i = 0; i <= n; i++)
		cin >> a[i], a[i] *= (n-i);

	while(r - l > eps) {
		double mid = (r + l) / 2.0;

		if(fun(mid) > 0)
			l = mid;
		else
			r = mid;
	}
	printf("%.5lf\n", l);
	return 0;
}
全部评论

相关推荐

今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,也有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务