这是我参与更文挑战的第18天,活动详情查看更文挑战
题目描述
对于给定的整数 n
, 如果n
的k
(k
>=2)进制数的所有数位全为1,则称 k
(k
>=2)是 n
的一个好进制。
以字符串的形式给出 n
, 以字符串的形式返回 n
的最小好进制。
示例 1:
输入:"13"
输出:"3"
解释:13 的 3 进制是 111。
示例 2:
输入:"4681"
输出:"8"
解释:4681 的 8 进制是 11111。
示例 3:
输入:"1000000000000000000"
输出:"999999999999999999"
解释:1000000000000000000 的 999999999999999999 进制是 11。
提示:
n
的取值范围是 。- 输入总是有效且没有前导 0。
解题思路
设 n
可以表示成位数为 ,进制为 k
的数,即 ,其中 表示 进制的数 。那么根据任意进制转换为十进制的方法,我们有:
根据上面的等式,在 时,显然有 ,并且根据二项式定理可以得到 ,因此我们得到了解决这题的关键不等式:
将两边同时开 次方,得到:
这样当 时, 的整数部分即为 的值。 由于题目的限制条件,我们只需要在 的范围内枚举 即可
代码
C++代码
#define LL long long
class Solution {
public:
string smallestGoodBase(string N) {
// (11...11)k = k^{s} + k^{s-1} + ... + k^1 + k^0 = n
// k^s < n < (k+1)^s
// k < n^{1/s} < k+1
LL n = stol(N);
LL ans = n - 1; // 将答案置为 s=1 的情况
for (int s = 59; s >= 2; --s) {
int k = pow(n, 1.0 / s); // k 为 n^{1/s} 的整数部分
if (k > 1) { // 判断 k 是否是一个合法的进制
LL sum = 1, mul = 1; // 计算 (11...11)k 对应的十进制值
for (int i = 1; i <= s; ++i) {
mul *= k;
sum += mul;
}
if (sum == n) {
ans = k;
break;
}
}
}
return to_string(ans);
}
};