二分法
二分法的主要思想就是在排完序的数组中对半查找,快速运算。
我们定义一个左端点为L,右端点为R,M为L,R中点,那么对于查找关键字Key,我们用M位置的对应值来跟他作比较,会有三种情况
(1)a[M]<key,那么我们查找的Key肯定在M右半边区域,所以此时我们将L=M+1
(2)a[M]>key,那么我们查找的Key肯定在M左半边区域,所以此时我们将R=M-1
(3)a[m]=key,那么我们找到了,直接跳出,此时M就是key值所在的位置
我们对于这个新的区间再次进行查找,直到找到我们要的答案;
如果一直没找到答案,我们的循环应该何时结束呢,应该很容易想到,就是当L>R的时候结束。
原来算法复杂度为N,二分算法复杂度 。对一个的数据原来的方法有可能需要次的查询,而二分只需要最多60多次的查询就可以找到,优势显而易见。
整数二分
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+9;
int a[maxn];
bool cha(int x,int n){
int l=1,r=n,mid;
while(l<r){
mid=(l+r)/2;
if(a[mid]==x)return 1;
else if(a[mid]>x) r=mid;
else l=mid+1;
}
return 0;
}
int main()
{
int t,n,m,ans;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
ans=0;
memset(a,0,sizeof a);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
if(cha(m-a[i],n)){
ans++;
if(a[i]==a[i-1]&&i!=1)
ans--;
}
}
printf("%d\n",ans);
}
return 0;
}
浮点数二分
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <math.h>
using namespace std;
const int maxn=1e6+9;
const double enp =1e-6;
double a[maxn];
#define pi acos(-1.0)
int n,m;
bool check(double x){
int num=0;
for(int i=0;i<n;i++){
num+=(int)(a[i]*a[i]*pi/x);
}
if(num>=m+1)return 1;
else return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%lf",&a[i]);
}
sort(a,a+n);
double l=0,r=a[n-1]*a[n-1]*pi,mid;
double ans=0;
while(l+enp<r){
mid=(l+r)/2.0;
if(check(mid)){
l=mid;
ans=mid;
}
else
r=mid;
}
printf("%.4f\n",ans);
}
return 0;
}