定义:
good base:当n在k进制下的数每一位都是1,则称k是n的good base
需求:找出n的最小good base
思路:二分查找
- 给一个n,n∈[3,10^18]
- n-1一定是n的good base
good base 越小位数越多
- 例如:13 goodbase 有12,3
- 12进制下是11
- 3进制下是111
//伪代码
num输入的数字
ans记录goodbase,初始化ans=num-1
定left=2,right=n-2,mid=(left+right)/2
外循环:1的位数j,j>=3
find=0//发现标志
内循环:left<=right //查找[left,right]区间满足j位1的goodbase
1.计算mid结果temp = mid^0+mid^1+...+mid^(j-1)
2.判断结果是否溢出,溢出:right = mid-1,mid = (right+left)/2
3.temp==num,找到一个goodbase,用ans记录,find=1,更新发现标志
2.temp>num,right = mid-1,mid = (right+left)/2
3.temp<num,left = mid+1,mid = (right+left)/2
find==0说明没找到,更新left=2,right=left-1 //left停留的位置计算出来一定是大于n
当right<2的时候说明从[2,num-2]所有的goodbase都遍历过了,break
例如13
ans = 12
left=2,right=11,mid=6
j = 3 //111
left<right,temp=1+6+36=43,temp>ans,right=mid-1=5,mid=(2+5)/2=3 //left=2,right=5,mid=3
left<right,temp=1+3+9=13,temp==ans,ans=mid,find=1,right=mid-1=2,left=2,mid=2//left=2,right=2,mid=2
j = 4 //1111
left==right,temp=1+2+4+8=15,temp>ans,right=mid-1=1,mid=(2+1)/2=1 //left=2,right=1,mid=1
right<2:break;
ans=3
//java
import java.math.BigInteger;
class Solution {
public String smallestGoodBase(String n) {
long num = 0;
char[] c_num = n.toCharArray();
for(int i=0;i<n.length();i++) {
num = num*10+c_num[i]-'0';
}
if(num<3) return null;
long ans = num-1; //11
long left = 2;
long right = ans-1;
long mid = (left+right)>>1;
int find = 0;
for(int j=3;;j++) {//从111开始逼近
find = 0;
while(left<=right) {
long temp = calc(mid,j);//a^0+a^1+a^2...a^j-1
if(temp==-1) {
//溢出的数据按照temp>num处理
right = mid - 1;
mid = (left+right)>>1;
}
else if(temp==num) {
ans=mid;
find = 1;
right = mid-1;
left = 2;
mid = (left+right)>>1;
break;
}else if(temp<num){
left = mid + 1;
mid = (left+right)>>1;
}else {
right = mid - 1;
mid = (left+right)>>1;
}
}
if(right<2)//遍历到j位的时候已经没有进制满足了
break;
if(find==0) {
right = left-1;
left = 2;
mid = (left+right)>>1;
}
}
return new Long(ans).toString();
}
public long calc(long num,long num1) {//num
if(num>=999999999) return -1;
BigInteger ans = new BigInteger("0");
BigInteger number = new BigInteger(new Long(num).toString());
for(int i=0;i<num1;i++) {
if(i==0)
ans = ans.add(new BigInteger("1"));
else {
BigInteger temp = new BigInteger("1");
for(int j=0;j<i;j++) {
temp = temp.multiply(number);
}
ans = ans.add(temp);
}
}
String ttemp = ans.toString();
char[] ans2 = ttemp.toCharArray();
if(ttemp.length()>=20) return -1;
if(ans2.length==19) {
if(ans2[0]>'1') return -1;
else {
for(int ff=1;ff<ttemp.length();ff++) {
if(ff!='0')
return -1;
}
}
}
long ans3 = 0;
for(int ii=0;ii<ttemp.length();ii++) {
ans3 = ans3*10 + ans2[ii]-'0';
}
return ans3;
}
}