90
90
91
91
<!-- solution:start -->
92
92
93
- ### 方法一
93
+ ### 方法一:枚举 + 组合数学
94
+
95
+ 我们可以考虑枚举所有长度为 $n$ 的回文数,判断它们是否是 $k$ 回文数。由于回文数的性质,我们只需要枚举前半部分的数字,然后将其反转拼接到后面即可。
96
+
97
+ 前半部分的数字长度为 $\lfloor \frac{n - 1}{2} \rfloor$,那么前半部分的数字范围是 $[ 10^{\lfloor \frac{n - 1}{2} \rfloor}, 10^{\lfloor \frac{n - 1}{2} \rfloor + 1})$。我们可以将前半部分的数字拼接到后面,形成一个长度为 $n$ 的回文数。注意到,如果 $n$ 是奇数,则需要将中间的数字做特殊处理。
98
+
99
+ 然后,我们判断该回文数是否是 $k$ 回文数,如果是,则统计该回文数的所有排列组合。为了避免重复,我们可以使用一个集合 $\textit{vis}$ 来存储已经出现过的回文数的每个最小排列。如果该回文数的最小排列已经出现过,则跳过该回文数。否则,我们统计该回文数有多少个不重复的排列组合,添加到答案中。
100
+
101
+ 我们可以使用一个数组 $\textit{cnt}$ 来统计每个数字出现的次数,然后使用组合数学的公式计算排列组合的数量。具体来说,假设数字 $0$ 出现了 $x_0$ 次,数字 $1$ 出现了 $x_1$ 次,...,数字 $9$ 出现了 $x_9$ 次,那么该回文数的排列组合数量为:
102
+
103
+ $$
104
+ \frac{(n - x_0) \cdot (n - 1)!}{x_0! \cdot x_1! \cdots x_9!}
105
+ $$
106
+
107
+ 其中 $(n - x_0)$ 表示最高位可以选择除 $0$ 以外的所有数字,而 $(n - 1)!$ 表示除最高位以外的所有数字的排列组合数量,然后我们除以每个数字出现的次数的阶乘,避免重复。
108
+
109
+ 最后,我们将所有的排列组合数量相加,得到最终的答案。
110
+
111
+ 时间复杂度 $({10}^m \times n \times \log n)$,空间复杂度 $O({10}^m \times n)$,其中 $m = \lfloor \frac{n - 1}{2} \rfloor$。
94
112
95
113
<!-- tabs:start -->
96
114
@@ -270,6 +288,49 @@ func reverseString(s string) string {
270
288
#### TypeScript
271
289
272
290
``` ts
291
+ function countGoodIntegers(n : number , k : number ): number {
292
+ const fac = factorial (n );
293
+ let ans = 0 ;
294
+ const vis = new Set <string >();
295
+ const base = Math .pow (10 , Math .floor ((n - 1 ) / 2 ));
296
+
297
+ for (let i = base ; i < base * 10 ; i ++ ) {
298
+ let s = ` ${i } ` ;
299
+ const rev = reverseString (s );
300
+ if (n % 2 === 1 ) {
301
+ s += rev .substring (1 );
302
+ } else {
303
+ s += rev ;
304
+ }
305
+
306
+ if (+ s % k !== 0 ) {
307
+ continue ;
308
+ }
309
+
310
+ const bs = Array .from (s ).sort ();
311
+ const t = bs .join (' ' );
312
+
313
+ if (vis .has (t )) {
314
+ continue ;
315
+ }
316
+
317
+ vis .add (t );
318
+
319
+ const cnt = Array (10 ).fill (0 );
320
+ for (const c of t ) {
321
+ cnt [+ c ]++ ;
322
+ }
323
+
324
+ let res = (n - cnt [0 ]) * fac [n - 1 ];
325
+ for (const x of cnt ) {
326
+ res /= fac [x ];
327
+ }
328
+ ans += res ;
329
+ }
330
+
331
+ return ans ;
332
+ }
333
+
273
334
function factorial(n : number ): number [] {
274
335
const fac = Array (n + 1 ).fill (1 );
275
336
for (let i = 1 ; i <= n ; i ++ ) {
@@ -281,24 +342,90 @@ function factorial(n: number): number[] {
281
342
function reverseString(s : string ): string {
282
343
return s .split (' ' ).reverse ().join (' ' );
283
344
}
345
+ ```
284
346
285
- function countGoodIntegers(n : number , k : number ): number {
347
+ #### Rust
348
+
349
+ ``` rust
350
+ impl Solution {
351
+ pub fn count_good_integers (n : i32 , k : i32 ) -> i64 {
352
+ use std :: collections :: HashSet ;
353
+ let n = n as usize ;
354
+ let k = k as i64 ;
355
+ let mut fac = vec! [1_i64 ; n + 1 ];
356
+ for i in 1 ..= n {
357
+ fac [i ] = fac [i - 1 ] * i as i64 ;
358
+ }
359
+
360
+ let mut ans = 0 ;
361
+ let mut vis = HashSet :: new ();
362
+ let base = 10_i64 . pow (((n - 1 ) / 2 ) as u32 );
363
+
364
+ for i in base .. base * 10 {
365
+ let s = i . to_string ();
366
+ let rev : String = s . chars (). rev (). collect ();
367
+ let full_s = if n % 2 == 0 {
368
+ format! (" {}{}" , s , rev )
369
+ } else {
370
+ format! (" {}{}" , s , & rev [1 .. ])
371
+ };
372
+
373
+ let num : i64 = full_s . parse (). unwrap ();
374
+ if num % k != 0 {
375
+ continue ;
376
+ }
377
+
378
+ let mut arr : Vec <char > = full_s . chars (). collect ();
379
+ arr . sort_unstable ();
380
+ let t : String = arr . iter (). collect ();
381
+ if vis . contains (& t ) {
382
+ continue ;
383
+ }
384
+ vis . insert (t );
385
+
386
+ let mut cnt = vec! [0 ; 10 ];
387
+ for c in arr {
388
+ cnt [c as usize - '0' as usize ] += 1 ;
389
+ }
390
+
391
+ let mut res = (n - cnt [0 ]) as i64 * fac [n - 1 ];
392
+ for & x in & cnt {
393
+ if x > 0 {
394
+ res /= fac [x ];
395
+ }
396
+ }
397
+ ans += res ;
398
+ }
399
+
400
+ ans
401
+ }
402
+ }
403
+ ```
404
+
405
+ #### JavaScript
406
+
407
+ ``` js
408
+ /**
409
+ * @param {number} n
410
+ * @param {number} k
411
+ * @return {number}
412
+ */
413
+ var countGoodIntegers = function (n , k ) {
286
414
const fac = factorial (n);
287
415
let ans = 0 ;
288
- const vis = new Set < string > ();
416
+ const vis = new Set ();
289
417
const base = Math .pow (10 , Math .floor ((n - 1 ) / 2 ));
290
418
291
419
for (let i = base; i < base * 10 ; i++ ) {
292
- let s = i . toString ( );
420
+ let s = String (i );
293
421
const rev = reverseString (s);
294
422
if (n % 2 === 1 ) {
295
423
s += rev .substring (1 );
296
424
} else {
297
425
s += rev;
298
426
}
299
427
300
- const num = parseInt (s , 10 );
301
- if (num % k !== 0 ) {
428
+ if (parseInt (s, 10 ) % k !== 0 ) {
302
429
continue ;
303
430
}
304
431
@@ -313,7 +440,7 @@ function countGoodIntegers(n: number, k: number): number {
313
440
314
441
const cnt = Array (10 ).fill (0 );
315
442
for (const c of t) {
316
- cnt [+ c ]++ ;
443
+ cnt[parseInt (c, 10 ) ]++ ;
317
444
}
318
445
319
446
let res = (n - cnt[0 ]) * fac[n - 1 ];
@@ -324,6 +451,18 @@ function countGoodIntegers(n: number, k: number): number {
324
451
}
325
452
326
453
return ans;
454
+ };
455
+
456
+ function factorial (n ) {
457
+ const fac = Array (n + 1 ).fill (1 );
458
+ for (let i = 1 ; i <= n; i++ ) {
459
+ fac[i] = fac[i - 1 ] * i;
460
+ }
461
+ return fac;
462
+ }
463
+
464
+ function reverseString (s ) {
465
+ return s .split (' ' ).reverse ().join (' ' );
327
466
}
328
467
```
329
468
0 commit comments