For an integer n, we call k>=2 a good base of n, if all digits of n base k are 1.
Now given a string representing n, you should return the smallest good base of n in string format.
Example 1:
Input: "13" Output: "3" Explanation: 13 base 3 is 111.
Example 2:
Input: "4681" Output: "8" Explanation: 4681 base 8 is 11111.
Example 3:
Input: "1000000000000000000" Output: "999999999999999999" Explanation: 1000000000000000000 base 999999999999999999 is 11.
Note:
- The range of n is [3, 10^18].
- The string representing n is always valid and will not have leading zeros.
题目理解:
给定一个整数a,将其从十进制转换为N进制A,如果A的每一位数字都是1,那么将N成为“好进制”,问对于一个给定的整数,其最小的“好进制”是多少
解题思路:
基本思路就是遍历所有进制,如果转换之后的数的数字全部都是1,就返回它。
首先是判断a的N进制是不是全为1,采用的方式是每次减1,然后除以N,如果每次除法都能整除,那么a的N进制就是全为1,这个可以自己举例子理解
为了减小复杂度,进制N一定是a-1的因子,因此进制的范围就缩小到了2~N的平方根。在考虑每一个因子i的时候,要注意(a-1)/i也是因子
由于a的范围是10^18,因此N的范围是10^9,这个复杂度还是不能通过全部样例,因此还要进一步缩小范围。考虑到,如果a的N进制是11,那么N就是a-1,如果aN进制是111,那么N一定小于a的三次根,如果位数大于3,那么N就会更小,所以如果单独考虑了111的情况,那么N的范围就能缩小到2~a的三次根。111的处理情况实际上就是解方程,不细讲。此时的复杂度可以通过样例检测。
import java.math.BigInteger;
class Solution {
public boolean judge(long num, long base){
if(base == 1)
return false;
num -= 1;
while(num > 0 && num % base == 0){
num /= base;
num -= 1;
}
return num == 0;
}
public String smallestGoodBase(String n) {
long num = Long.valueOf(n);
long temp = num - 1;
long res = temp;
for(long i = 1; i <= Math.pow(num, 1.0 / 3); i++){
if((temp) % i != 0)
continue;
if(judge(num, i))
return String.valueOf(i);
if(judge(num, (temp) / i))
res = (temp) / i;
}
long root = (long) Math.sqrt(4 * num - 3);
if(Math.pow(root, 2) == 4 * num - 3) {
long cur = (-1 + root);
if(cur != 2 && cur % 2 == 0)
res = Math.min(cur / 2, res);
}
return String.valueOf(res);
}
}