今天又是困难题,不会做,在看官方题解和其他人的题解终于明白了,记录一下。
483最小好进制
思路
做题前的分析:
- 因为n的范围为
3
≤
n
≤
1
0
18
3\le n \le 10^{18}
3≤n≤1018,上限远远超过
1e7
,所以不能使用暴力方法; - 因为java中的long的范围最大为 2 63 − 1 2^{63}-1 263−1 大于 1 0 18 10^{18} 1018 ,所以可以使用long类型的变量转存n,方便进行计算;
- 由题意和示例可以分析得出,最终的答案
k
的值范围在 2 ≤ k ≤ ( n − 1 ) 2\le k \le (n-1) 2≤k≤(n−1); - 当 k = 2 、 n = 1 0 18 k=2、n=10^{18} k=2、n=1018时,如果满足条件,答案不会超过60,又因为 k ≠ n , k ≠ 1 k \ne n,k\ne 1 k=n,k=1,所以答案的范围在 2 ≤ l e n ≤ 60 2\le len \le 60 2≤len≤60,一般情况下为 2 ≤ l e n ≤ l o g 2 ( n ) 2\le len \le log_2(n) 2≤len≤log2(n);
- 当
n
=
k
0
+
k
1
+
.
.
.
.
+
k
m
n=k^0+k^1+....+k^m
n=k0+k1+....+km时,可得
n
>
k
m
n>k^m
n>km,由
二项式定理
得 k m < n < k m + 1 k^m < n < k^{m+1} km<n<km+1,所以 k < n 1 m < k + 1 k<n^{\frac{1}{m}}<k+1 k<nm1<k+1,其中m为正整数;
代码
class Solution {
public String smallestGoodBase(String n) {
//因为n的值最大为10的18次方,小于2的63次方-1,所以可以使用long转存
long num = Long.parseLong(n);
//通过分析,发现len的值在2-60,k的值在2-(n-1)
int maxLen = (int)(Math.log(1.0 * num) / Math.log(2.0));
for (int len = 2; len<=maxLen;len++)
{
//获取k
long k = (long)Math.pow(num,1.0/len);
if (countNum(k,len)==num)
return String.valueOf(k);
}
return String.valueOf(num-1);
}
public long countNum(long k, int len)
{
long sum = 1;
//计算k的0至(len-1)次方的和+1
//每一次的sum都是k的0至(i-1)次方的和+1
//即在k进制下(i+1)个1对应的十进制数
for (int i=0;i<len;i++)
sum = sum * k + 1;
return sum;
}
}