练习使用二分法
高中的时候学过对分查找,但是还没怎么使用过,这次试试看。
题目:
一开始我想的是用快速幂求(因为最近学了这个,所以想遛一遛),结果因为数据太大中途归零出错了,这段代码在下面:
#include<iostream>
using namespace std;
long long pow(long long base,long long index)//快速幂
{
long long ans=1;
while(index>0)
{
if(index&1)
ans=ans*base;
base=base*base;
index=index>>1;
}
return ans;
}
int main()
{
long long x=1,n,low,ans;
cin>>n;
low=pow(10,n-1);
while(pow(x,x)<low)
x=x<<1;
long long lst=(x>>1)+1,hst=x;
while(lst<hst)
{
long long mid=(lst+hst)>>1;
if(pow(mid,mid)==low)//恰好相等情况
{
ans=pow(mid,mid);
break;
}
else if(pow(mid,mid)>low)
{
if(pow(mid-1,mid-1)<low)//一般找到情况
{
ans=pow(mid,mid);
break;
}
hst=mid;
}
else if(pow(mid,mid)<low)
lst=mid;
}
cout<<ans;
return 0;
}
无奈之下找了找大佬们的方法,发现他们都用了cmath的log10(double)这个函数。
这个东西可以直接求n是几位数,即 n的位数=log10(n)+1,这样就用不到我那个麻烦的快速幂了,就考虑后面的二分法具体的某些点了。
一个是循环结束条件,看了看大佬并没有特别写结束返回的值,最后直接用l,的确可以,while循环条件是l<h,所以最后l>=h,而要求的是不小于n位数的值,所以用l就可以了,还能保证求出的是最小值。
最后
#include<iostream>
#include<cmath>
using namespace std;
#define LL long long int
int main()
{
int n;
LL l=1,h=2e9;
cin>>n;
while(l<h)
{
LL mid=(l+h)>>1;
LL len=mid*log10(mid)+1;
if(len<n)
l=mid+1;
else
h=mid;
}
cout<<l;
return 0;
}
一般来说
int low=0,high=n-1;
while(low<high)
{
int mid=(low+high)>>1;
if(mid==target)
return mid;
else if(mid<target)
low=mid+1;
else
high=mid-1;
}