二分查找 -Binary_Search
先介绍一下二分的基本思路。
猜数游戏时,男神说:
在长度为n的区间内任选一数,他能在至多 log2n次 准确猜出。
他会读心术么?显然,他利用了二分的思想:
int Binary_Search(int L[],int target,int left,int right)
{
while(right>=left)
{
int mid=(left+right)/2;
if(L[mid]==target)return mid;
if(L[mid]>target)
right=mid-1;
else if(L[mid]<target)
left=mid+1;
}
return 0;
}
对于浮点型的二分问题,
可以right-left>eps为界【#define eps 1e-6】
题目背景
tz大佬从遥远的喜马拉雅山挖出了一个NN阶的函数。
为了研究这个神奇的函数,tzdalao把函数拉到了编程俱乐部。
题目描述
这棵函数是N次函数,经过观察发现,在闭区间 [l,r] 内函数存在一个极大值点,请求出这个极大值点x.
输入格式
第一行,一个正整数N和两个实数 l、r,表示闭区间范围。
第二行,N+1个实数,从左到右依次表示函数的系数。
输出格式
输出x的值,四舍五入保留5位小数。
输入 #1
3 -0.9981 0.5
1 -3 -3 1
输出 #1
-0.41421
**题解:**当我们知道一阶导数的正负情况,即可判断函数的增减,进而缩小查找的范围。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define eps 1e-7
int n;
double left,right,mid,xs[1005];
double calc(double x)//求导
{
double ans=0;
for(int i=1;i<=n;i++)
ans+=(i*xs[n-i]*pow(x,i-1));//次数*系数*x^次数-1
return ans;
}
int main()
{
double ds;
scanf("%d%lf%lf",&n,&left,&right);
for(int i=0;i<=n;i++)
scanf("%lf",&xs[i]);
while(right-left>eps)
{
mid=left+(right-left)/2.0;//防越界
ds=calc(mid);//求在mid处的导数
if(ds>0)left=mid;//增
else if(ds<0)right=mid;//减
}
printf("%.5lf\n",mid);
return 0;
}