CF1485A题解
很有趣的思维题,我们先来考虑操作二。
我们先来看一个例子:
\(a=44,b=5\) 此时,我们要除的次数显然为 \(3\)。
显然得出要除的次数就是 \(\left\lceil\log_ba\right\rceil\)。
接着,我们再考虑操作一。
显然进行一次操作一后结果是这个: \(\left\lceil\log_{b+1}a+1\right\rceil\)。
我们可以看出先加后除要比先除后加好,给出一个简单的证明:
假设先进行操作二再进行操作一,则为
\[\left\lceil\log_{b+1} \left\lfloor\dfrac{a}{b}\right\rfloor+2\right\rceil
\]
但如果先进行操作一再进行操作二,则为
\[\left\lceil\log_{b+1} \left\lfloor\dfrac{a}{b+1}\right\rfloor+2\right\rceil
\]
显然,我们有
\[\left\lceil\log_{b+1} \left\lfloor\dfrac{a}{b}\right\rfloor+2\right\rceil\le\left\lceil\log_{b+1} \left\lfloor\dfrac{a}{b+1}\right\rfloor+2\right\rceil
\]
于是我们一定有先加后乘比先乘后加划算。
我们又知道,\(b\) 最坏为 \(1\),\(a\) 最坏为 \(10^9\),易得最坏情况下不会超过 \(40\) 次,那么我们就可以枚举进行几次操作二,然后求出在此时要多少次操作一。
注意:不能用log来求!精度有误差,会错的
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int divide(int a,int b){//求出操作一次数
int cnt=0;
while(a){
a/=b;
cnt++;
if(cnt>100)break;
}
return cnt;
}
int main(){
int t;
cin>>t;
while(t--){
int a,b;
cin>>a>>b;
int minx=100000;
for(int i=0;i<=40;++i){//枚举操作二次数
minx=min(divide(a,b+i)+i,minx);
}
cout<<minx<<endl;
}
return 0;
}