题目背景
tz大佬从遥远的喜马拉雅山挖出了一个N阶的函数,
为了研究这个神奇的函数,tzdalao把函数拉到了编程俱乐部。
题目描述
这棵函数是N次函数,经过观察发现,在闭区间[l,r]内函数存在一个极大值点,请求出这个极大值点xx。
输入输出格式
输入格式:
第一行,一个正整数N和两个实数l、r,表示闭区间范围。
第二行,N+1个实数,从左到右依次表示函数的系数。
输出格式:
输出x的值,四舍五入保留5位小数。
输入输出样例
输入样例#1:
3 -0.9981 0.5
1 -3 -3 1
输出样例#1:
-0.41421
说明
上述样例是n = 3,x^3 -3x^2 - 3x + 1
解题思路:这道题用二分法即可a掉(一开始想到二分不敢往下做了,蠢爆了),但是要注意精确度,这里保留五位小数,即左边界跟有边界相差不大于1e-5即可,此外还要注意边界问题。
代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
double l,r,mid,sum1,sum2,sum,m[1005];
//sum1、sum2、sum依次记录左边界、右边界、中间值求和结果,数组m用于记录系数
int main()
{
scanf("%d %lf %lf",&n,&l,&r);
for(int i=1;i<=n+1;i++)
scanf("%lf",&m[i]);
sum1=sum2=0;
for(int i=1;i<=n-1;i++)
{
sum1+=m[i]*(n-i+1)*pow(l,n-i);//这里的意思是将左右边界带入原函数求导的之后函数中
sum2+=m[i]*(n-i+1)*pow(r,n-i);;
}
sum1+=m[n];
sum2+=m[n];
if(sum1==0)
printf("%.5f\n",l);
else if(sum2==0)
printf("%5.f\n",r);
else
{
mid=(l+r)/2;
while(r-l>0.00001)
{
sum=0;
for(int i=1;i<=n-1;i++)
sum+=m[i]*(n-i+1)*pow(mid,n-i);
sum+=m[n];//因为第n项求导之后是一个常数,所以直接加上即可
if(sum>0)
{
l=mid+0.000001;
mid=(l+r)/2;
}
else if(sum<0)
{
r=mid+0.000001;
mid=(l+r)/2;
}
if(sum==0)
break;
}
printf("%.5f\n",mid);
}
return 0;
}