题目:
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.
思路:
这道题目的基本思路是二分查找。注意到不同的k将会对应不同的长度d,使得11...1(一共d位)在k进制下表示n。而最小的k就意味着最大的d。所以我们就让d从大到小循环,看看11...1(一共d位)是否可以在某个base k下构成n。
对于长度为d的这个数,k的最小值显然是1,最大值则是power(tn, 1.0 / d) + 1。于是我们在这个区间内二分查找合适的k,并返回即可。
代码:
class Solution {
public:
string smallestGoodBase(string n) {
unsigned long long tn = static_cast<unsigned long long>(stoll(n));
unsigned long long x = 1;
for (int i = 62; i >= 1; --i) {
if ((x << i) < tn) {
unsigned long long cur = helper(tn, i);
if (cur != 0) {
return to_string(cur);
}
}
}
return to_string(tn - 1);
}
private:
unsigned long long helper(unsigned long long n,int d) {
double tn = static_cast<double>(n);
unsigned long long right = static_cast<unsigned long long>(pow(tn, 1.0 / d) + 1);
unsigned long long left = 1;
while (left <= right){
unsigned long long mid= left + (right - left) / 2;
unsigned long long sum = 1,cur = 1;
for (int i = 1;i <= d; ++i) {
cur *= mid;
sum += cur;
}
if (sum == n) {
return mid;
}
if (sum > n) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
return 0;
}
};