Skip to content

Commit ec962fe

Browse files
authored
feat: add solutions for lc No.3855 (#5059)
1 parent f186cb5 commit ec962fe

7 files changed

Lines changed: 565 additions & 6 deletions

File tree

solution/3800-3899/3855.Sum of K-Digit Numbers in a Range/README.md

Lines changed: 194 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,32 +84,223 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3800-3899/3855.Su
8484

8585
<!-- solution:start -->
8686

87-
### 方法一
87+
### 方法一:数学 + 快速幂
88+
89+
我们从低位到高位枚举每一位数字 $x$,假设当前为第 $i$ 位($i$ 从 $0$ 开始),相当于填了一个数字 $x \cdot 10^i$,其余的 $k - 1$ 位数字,每一位都有 $r - l + 1$ 个选择,所以当前位的贡献为 $x \cdot 10^i \cdot (r - l + 1)^{k - 1}$。对于 $x$ 的选择范围是 $[l, r]$,所以 $x$ 的总和为 $\frac{(l + r) \cdot (r - l + 1)}{2}$,因此所有数字的总和为:
90+
91+
$$
92+
\begin{aligned}
93+
&\sum_{i = 0}^{k - 1} \frac{(l + r) \cdot (r - l + 1)}{2} \cdot (r - l + 1)^{k - 1} \cdot 10^i \\
94+
= &\frac{(l + r) \cdot (r - l + 1)}{2} \cdot (r - l + 1)^{k - 1} \cdot \frac{10^k - 1}{9}
95+
\end{aligned}
96+
$$
97+
98+
由于 $k$ 的范围是 $[1, 10^9]$,我们需要使用快速幂来计算 $(r - l + 1)^{k - 1}$ 和 $10^k$,另外除法需要使用费马小定理来计算 $9$ 的逆元。
99+
100+
时间复杂度 $O(\log k)$,空间复杂度 $O(1)$。
88101

89102
<!-- tabs:start -->
90103

91104
#### Python3
92105

93106
```python
107+
class Solution:
108+
def sumOfNumbers(self, l: int, r: int, k: int) -> int:
109+
mod = 10**9 + 7
110+
111+
n = r - l + 1
112+
113+
# ((l + r) * (r - l + 1) // 2) % mod
114+
total = (l + r) * n // 2 % mod
94115

116+
# pow(r - l + 1, k - 1, mod)
117+
part1 = pow(n % mod, k - 1, mod)
118+
119+
# (pow(10, k, mod) - 1)
120+
part2 = (pow(10, k, mod) - 1) % mod
121+
122+
# Fermat inverse of 9
123+
inv9 = pow(9, mod - 2, mod)
124+
125+
ans = total
126+
ans = ans * part1 % mod
127+
ans = ans * part2 % mod
128+
ans = ans * inv9 % mod
129+
130+
return ans
95131
```
96132

97133
#### Java
98134

99135
```java
100-
136+
class Solution {
137+
public int sumOfNumbers(int l, int r, int k) {
138+
final int mod = 1_000_000_007;
139+
140+
long n = r - l + 1L;
141+
142+
// ((l + r) * (r - l + 1) // 2) % mod
143+
long sum = (long) (l + r) * n / 2 % mod;
144+
145+
// pow(r - l + 1, k - 1, mod)
146+
long part1 = qpow(n % mod, k - 1, mod);
147+
148+
// (pow(10, k, mod) - 1)
149+
long part2 = (qpow(10, k, mod) - 1 + mod) % mod;
150+
151+
// pow(9, mod - 2, mod) (Fermat inverse of 9)
152+
long inv9 = qpow(9, mod - 2, mod);
153+
154+
long ans = sum;
155+
ans = ans * part1 % mod;
156+
ans = ans * part2 % mod;
157+
ans = ans * inv9 % mod;
158+
159+
return (int) ans;
160+
}
161+
162+
private int qpow(long a, int n, int mod) {
163+
long ans = 1;
164+
a %= mod;
165+
for (; n > 0; n >>= 1) {
166+
if ((n & 1) == 1) {
167+
ans = ans * a % mod;
168+
}
169+
a = a * a % mod;
170+
}
171+
return (int) ans;
172+
}
173+
}
101174
```
102175

103176
#### C++
104177

105178
```cpp
106-
179+
class Solution {
180+
public:
181+
int sumOfNumbers(int l, int r, int k) {
182+
const int mod = 1'000'000'007;
183+
184+
long long n = 1LL * r - l + 1;
185+
186+
// ((l + r) * (r - l + 1) / 2) % mod
187+
long long sum = 1LL * (l + r) * n / 2 % mod;
188+
189+
// pow(r - l + 1, k - 1, mod)
190+
long long part1 = qpow(n % mod, k - 1, mod);
191+
192+
// (pow(10, k, mod) - 1)
193+
long long part2 = (qpow(10, k, mod) - 1 + mod) % mod;
194+
195+
// Fermat inverse of 9
196+
long long inv9 = qpow(9, mod - 2, mod);
197+
198+
long long ans = sum;
199+
ans = ans * part1 % mod;
200+
ans = ans * part2 % mod;
201+
ans = ans * inv9 % mod;
202+
203+
return (int) ans;
204+
}
205+
206+
private:
207+
long long qpow(long long a, long long n, int mod) {
208+
long long ans = 1;
209+
a %= mod;
210+
while (n > 0) {
211+
if (n & 1) {
212+
ans = ans * a % mod;
213+
}
214+
a = a * a % mod;
215+
n >>= 1;
216+
}
217+
return ans;
218+
}
219+
};
107220
```
108221
109222
#### Go
110223
111224
```go
225+
func sumOfNumbers(l int, r int, k int) int {
226+
const mod int64 = 1_000_000_007
227+
228+
n := int64(r - l + 1)
229+
230+
// ((l + r) * (r - l + 1) / 2) % mod
231+
sum := int64(l+r) * n / 2 % mod
232+
233+
// pow(r - l + 1, k - 1, mod)
234+
part1 := qpow(n%mod, int64(k-1), mod)
235+
236+
// (pow(10, k, mod) - 1)
237+
part2 := (qpow(10, int64(k), mod) - 1 + mod) % mod
238+
239+
// Fermat inverse of 9
240+
inv9 := qpow(9, mod-2, mod)
241+
242+
ans := sum
243+
ans = ans * part1 % mod
244+
ans = ans * part2 % mod
245+
ans = ans * inv9 % mod
246+
247+
return int(ans)
248+
}
249+
250+
func qpow(a int64, n int64, mod int64) int64 {
251+
a %= mod
252+
var ans int64 = 1
253+
for n > 0 {
254+
if n&1 == 1 {
255+
ans = ans * a % mod
256+
}
257+
a = a * a % mod
258+
n >>= 1
259+
}
260+
return ans
261+
}
262+
```
263+
264+
#### TypeScript
265+
266+
```ts
267+
function sumOfNumbers(l: number, r: number, k: number): number {
268+
const mod = 1_000_000_007n;
269+
270+
const n = BigInt(r - l + 1);
271+
272+
// ((l + r) * (r - l + 1) / 2) % mod
273+
const sum = ((BigInt(l + r) * n) / 2n) % mod;
274+
275+
// pow(r - l + 1, k - 1, mod)
276+
const part1 = qpow(n % mod, BigInt(k - 1), mod);
277+
278+
// (pow(10, k, mod) - 1)
279+
const part2 = (qpow(10n, BigInt(k), mod) - 1n + mod) % mod;
280+
281+
// Fermat inverse of 9
282+
const inv9 = qpow(9n, mod - 2n, mod);
283+
284+
let ans = sum;
285+
ans = (ans * part1) % mod;
286+
ans = (ans * part2) % mod;
287+
ans = (ans * inv9) % mod;
288+
289+
return Number(ans);
290+
}
112291

292+
function qpow(a: bigint, n: bigint, mod: bigint): bigint {
293+
a %= mod;
294+
let ans = 1n;
295+
while (n > 0n) {
296+
if ((n & 1n) === 1n) {
297+
ans = (ans * a) % mod;
298+
}
299+
a = (a * a) % mod;
300+
n >>= 1n;
301+
}
302+
return ans;
303+
}
113304
```
114305

115306
<!-- tabs:end -->

0 commit comments

Comments
 (0)