Skip to content

Commit c2c11c9

Browse files
committed
feat: add solutions to lc problem: No.0483
No.0483.Smallest Good Base
1 parent ab2ddaf commit c2c11c9

File tree

4 files changed

+316
-1
lines changed

4 files changed

+316
-1
lines changed

solution/0400-0499/0483.Smallest Good Base/README.md

+193
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,215 @@
4949

5050
<!-- 这里可写通用的实现逻辑 -->
5151

52+
**方法一:数学**
53+
54+
假设 $n$ 在 $k$ 进制下的所有位数均为 $1$,且位数为 $m+1$,那么有式子 ①:
55+
56+
$$
57+
n=k^0+k^1+k^2+...+k^m
58+
$$
59+
60+
当 $m=0$ 时,上式 $n=1$,而题目 $n$ 取值范围为 $[3, 10^{18}]$,因此 $m>0$。
61+
62+
当 $m=1$ 时,上式 $n=k^0+k^1=1+k$,即 $k=n-1>=2$。
63+
64+
我们来证明一般情况下的两个结论,以帮助解决本题。
65+
66+
**结论一:** $m<\log _{k} n$
67+
68+
注意到式子 ① 是个首项为 $1$,且公比为 $k$ 的等比数列。利用等比数列求和公式,我们可以得出:
69+
70+
$$
71+
n=\frac{1-k^{m+1}}{1-k}
72+
$$
73+
74+
变形得:
75+
76+
$$
77+
k^{m+1}=k \times n-n+1 < k \times n
78+
$$
79+
80+
移项得:
81+
82+
$$
83+
m<\log _{k} n
84+
$$
85+
86+
题目 $n$ 取值范围为 $[3, 10^{18}]$,又因为 $k>=2$,因此 $m<\log _{k} n<\log _{2} 10^{18}<60$。
87+
88+
**结论二:** $k=\left \lfloor \sqrt[m]{n} \right \rfloor $
89+
90+
$$
91+
n=k^0+k^1+k^2+...+k^m>k^m
92+
$$
93+
94+
根据二项式定理:
95+
96+
$$
97+
(a+b)^{n}=\sum_{k=0}^{n}\left(\begin{array}{l}
98+
n \\
99+
k
100+
\end{array}\right) a^{n-k} b^{k}
101+
$$
102+
103+
整合,可得:
104+
105+
$$
106+
(k+1)^{m}=\left(\begin{array}{c}
107+
m \\
108+
0
109+
\end{array}\right) k^{0}+\left(\begin{array}{c}
110+
m \\
111+
1
112+
\end{array}\right) k^{1}+\left(\begin{array}{c}
113+
m \\
114+
2
115+
\end{array}\right) k^{2}+\cdots+\left(\begin{array}{c}
116+
m \\
117+
m
118+
\end{array}\right) k^{m}
119+
$$
120+
121+
当 $m>1$ 时,满足:
122+
123+
$$
124+
\forall i \in[1, m-1],\left(\begin{array}{c}
125+
m \\
126+
i
127+
\end{array}\right)>1
128+
$$
129+
130+
所以有:
131+
132+
$$
133+
\begin{aligned}
134+
(k+1)^{m} &=\left(\begin{array}{c}
135+
m \\
136+
0
137+
\end{array}\right) k^{0}+\left(\begin{array}{c}
138+
m \\
139+
1
140+
\end{array}\right) k^{1}+\left(\begin{array}{c}
141+
m \\
142+
2
143+
\end{array}\right) k^{2}+\cdots+\left(\begin{array}{c}
144+
m \\
145+
m
146+
\end{array}\right) k^{m} \\
147+
&>k^{0}+k^{1}+k^{2}+\cdots+k^{m}=n
148+
\end{aligned}
149+
$$
150+
151+
即:
152+
153+
$$
154+
k < \sqrt[m]{n} < k+1
155+
$$
156+
157+
由于 $k$ 是整数,因此 $k=\left \lfloor \sqrt[m]{n} \right \rfloor $。
158+
159+
综上,依据结论一,我们知道 $m$ 的取值范围为 $[1,log_{k}n)$,且 $m=1$ 时必然有解。随着 $m$ 的增大,进制 $k$ 不断减小。所以我们只需要从大到小检查每一个 $m$ 可能的取值,利用结论二快速算出对应的 $k$ 值,然后校验计算出的 $k$ 值是否有效即可。如果 $k$ 值有效,我们即可返回结果。
160+
161+
时间复杂度 $O(log^{2}n)$。
162+
52163
<!-- tabs:start -->
53164

54165
### **Python3**
55166

56167
<!-- 这里可写当前语言的特殊实现逻辑 -->
57168

58169
```python
170+
class Solution:
171+
def smallestGoodBase(self, n: str) -> str:
172+
def cal(k, m):
173+
p = s = 1
174+
for i in range(m):
175+
p *= k
176+
s += p
177+
return s
59178

179+
num = int(n)
180+
for m in range(63, 1, -1):
181+
l, r = 2, num - 1
182+
while l < r:
183+
mid = (l + r) >> 1
184+
if cal(mid, m) >= num:
185+
r = mid
186+
else:
187+
l = mid + 1
188+
if cal(l, m) == num:
189+
return str(l)
190+
return str(num - 1)
60191
```
61192

62193
### **Java**
63194

64195
<!-- 这里可写当前语言的特殊实现逻辑 -->
65196

66197
```java
198+
class Solution {
199+
public String smallestGoodBase(String n) {
200+
long num = Long.parseLong(n);
201+
for (int len = 63; len >= 2; --len) {
202+
long radix = getRadix(len, num);
203+
if (radix != -1) {
204+
return String.valueOf(radix);
205+
}
206+
}
207+
return String.valueOf(num - 1);
208+
}
209+
210+
private long getRadix(int len, long num) {
211+
long l = 2, r = num - 1;
212+
while (l < r) {
213+
long mid = l + r >>> 1;
214+
if (calc(mid, len) >= num) r = mid;
215+
else l = mid + 1;
216+
}
217+
return calc(r, len) == num ? r : -1;
218+
}
219+
220+
private long calc(long radix, int len) {
221+
long p = 1;
222+
long sum = 0;
223+
for (int i = 0; i < len; ++i) {
224+
if (Long.MAX_VALUE - sum < p) {
225+
return Long.MAX_VALUE;
226+
}
227+
sum += p;
228+
if (Long.MAX_VALUE / p < radix) {
229+
p = Long.MAX_VALUE;
230+
} else {
231+
p *= radix;
232+
}
233+
}
234+
return sum;
235+
}
236+
}
237+
```
238+
239+
### **C++**
67240

241+
```cpp
242+
class Solution {
243+
public:
244+
string smallestGoodBase(string n) {
245+
long v = stol(n);
246+
int mx = floor(log(v) / log(2));
247+
for (int m = mx; m > 1; --m) {
248+
int k = pow(v, 1.0 / m);
249+
long mul = 1, s = 1;
250+
for (int i = 0; i < m; ++i) {
251+
mul *= k;
252+
s += mul;
253+
}
254+
if (s == v) {
255+
return to_string(k);
256+
}
257+
}
258+
return to_string(v - 1);
259+
}
260+
};
68261
```
69262
70263
### **...**

solution/0400-0499/0483.Smallest Good Base/README_EN.md

+83-1
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,95 @@
4848
### **Python3**
4949

5050
```python
51-
51+
class Solution:
52+
def smallestGoodBase(self, n: str) -> str:
53+
def cal(k, m):
54+
p = s = 1
55+
for i in range(m):
56+
p *= k
57+
s += p
58+
return s
59+
60+
num = int(n)
61+
for m in range(63, 1, -1):
62+
l, r = 2, num - 1
63+
while l < r:
64+
mid = (l + r) >> 1
65+
if cal(mid, m) >= num:
66+
r = mid
67+
else:
68+
l = mid + 1
69+
if cal(l, m) == num:
70+
return str(l)
71+
return str(num - 1)
5272
```
5373

5474
### **Java**
5575

5676
```java
77+
class Solution {
78+
public String smallestGoodBase(String n) {
79+
long num = Long.parseLong(n);
80+
for (int len = 63; len >= 2; --len) {
81+
long radix = getRadix(len, num);
82+
if (radix != -1) {
83+
return String.valueOf(radix);
84+
}
85+
}
86+
return String.valueOf(num - 1);
87+
}
88+
89+
private long getRadix(int len, long num) {
90+
long l = 2, r = num - 1;
91+
while (l < r) {
92+
long mid = l + r >>> 1;
93+
if (calc(mid, len) >= num) r = mid;
94+
else l = mid + 1;
95+
}
96+
return calc(r, len) == num ? r : -1;
97+
}
98+
99+
private long calc(long radix, int len) {
100+
long p = 1;
101+
long sum = 0;
102+
for (int i = 0; i < len; ++i) {
103+
if (Long.MAX_VALUE - sum < p) {
104+
return Long.MAX_VALUE;
105+
}
106+
sum += p;
107+
if (Long.MAX_VALUE / p < radix) {
108+
p = Long.MAX_VALUE;
109+
} else {
110+
p *= radix;
111+
}
112+
}
113+
return sum;
114+
}
115+
}
116+
```
57117

118+
### **C++**
119+
120+
```cpp
121+
class Solution {
122+
public:
123+
string smallestGoodBase(string n) {
124+
long v = stol(n);
125+
int mx = floor(log(v) / log(2));
126+
for (int m = mx; m > 1; --m) {
127+
int k = pow(v, 1.0 / m);
128+
long mul = 1, s = 1;
129+
for (int i = 0; i < m; ++i) {
130+
mul *= k;
131+
s += mul;
132+
}
133+
if (s == v) {
134+
return to_string(k);
135+
}
136+
}
137+
return to_string(v - 1);
138+
}
139+
};
58140
```
59141
60142
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class Solution {
2+
public:
3+
string smallestGoodBase(string n) {
4+
long v = stol(n);
5+
int mx = floor(log(v) / log(2));
6+
for (int m = mx; m > 1; --m) {
7+
int k = pow(v, 1.0 / m);
8+
long mul = 1, s = 1;
9+
for (int i = 0; i < m; ++i) {
10+
mul *= k;
11+
s += mul;
12+
}
13+
if (s == v) {
14+
return to_string(k);
15+
}
16+
}
17+
return to_string(v - 1);
18+
}
19+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Solution:
2+
def smallestGoodBase(self, n: str) -> str:
3+
def cal(k, m):
4+
p = s = 1
5+
for i in range(m):
6+
p *= k
7+
s += p
8+
return s
9+
10+
num = int(n)
11+
for m in range(63, 1, -1):
12+
l, r = 2, num - 1
13+
while l < r:
14+
mid = (l + r) >> 1
15+
if cal(mid, m) >= num:
16+
r = mid
17+
else:
18+
l = mid + 1
19+
if cal(l, m) == num:
20+
return str(l)
21+
return str(num - 1)

0 commit comments

Comments
 (0)