分值的思想
二分查找与二分答案
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; }