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;
}
posted @ 2021-05-08 15:50  endlessloop  阅读(53)  评论(0)    收藏  举报