二分-tz大佬的函数

题目背景

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;
}

猜你喜欢

转载自blog.csdn.net/qq_42891420/article/details/87543182