二分与三分

分值的思想

二分查找与二分答案

OPJ

二分01 求最接近元素

用longlong

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
long long n;
long long a1[100005];
int m;
long long a2[10005];

int main( ){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a1[i]);
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		scanf("%lld",&a2[i]);
	}
	
	for(int i=1;i<=m;i++){
		int left=1,right=n;
		int mid=0;
			while(left<right-1){
				mid=(left+right)/2;
				if(a1[mid]<a2[i]){
					left=mid;
				}
				else{
				//else{
					right=mid;
				}
				
			}
			//if(a1[mid]==a2[j]) printf("%lld\n",mid);
			if(a2[i]-a1[left]<=a1[right]-a2[i]){
				printf("%lld\n",a1[left]);
			}
			else printf("%lld\n",a1[right]);
		
	}
	return 0;
} 

核心部分

for(int i=1;i<=m;i++){
		int left=1,right=n;
		int mid=0;
			while(left<right-1){
				mid=(left+right)/2;
				if(a1[mid]<a2[i]){
					left=mid;
				}
				else{
				//else{
					right=mid;
				}
				
			}

二分02:求函数零点

浮点数的二分需要终止二分的条件,一般来说写到要求位数的下一位来终止

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
using namespace std;
double f(double mid){
	double ans=mid*mid*mid*mid*mid-15*mid*mid*mid*mid+85*mid*mid*mid-225*mid*mid+274*mid-121;
	return ans;
}
double k,midd;
int main( ){
	double left=1.5,right=2.4;
	while(left<right-0.0000001){
		midd=(left+right)/2;
		if(f(midd)<0){
			right=midd;
		}
		if(f(midd)>0){
			left=midd;
		}
		if(f(midd)==0){
			k=midd;
			printf("%.6lf",k);
			return 0;
		}
	}
	printf("%.6lf",midd);
	return 0;
} 

三分

对非单调性而有两段单调性的函数,可以进行列表排除

对二次函数的最值点进行求值,针对对称轴与区间的位置进行二分

注意的是,取三等分点的写法

\(t_1=l+\frac{1}{3}(r-l)\)

\(t_2=l+\frac{2}{3}(r-l)\)

二分的\(mid=\frac{l+r}{2}\)只是化简后的结果巧合

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;//其实一般精度*0.1=1e-6就可以了
int n;
double L,R;
double a[15];
//普通的求多项式
/*double F(double x)
{
 double f=0;
 for(int i=n;i>=0;i--)
 {
  double t=1;
  for(int j=1;j<=i;j++)
  t*=x;
  f+=a[i]*t;
 }
 return f;
}*/
//秦九韶算法从里到外逐层计算一次多项式的值
double F(double x)
{
 double sum=0;
 for(int i=n;i>=0;i--)
 sum=sum*x+a[i];
 return sum; 
}
int main()
{
 cin>>n>>L>>R;
 for(int i=n;i>=0;i--) cin>>a[i];
 while(fabs(L-R)>=eps)
 {
  double mid=(L+R)/2;
  if(F(mid+eps)>F(mid-eps)) L=mid;//舍弃左区间
  else R=mid;//舍弃右区间
 }
 printf("%.5lf",R);
 return 0;
}
posted @ 2019-12-05 22:14  刘子闻  阅读(160)  评论(0)    收藏  举报