9090
9191<!-- solution:start -->
9292
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$。
94112
95113<!-- tabs:start -->
96114
@@ -270,6 +288,49 @@ func reverseString(s string) string {
270288#### TypeScript
271289
272290``` 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+
273334function factorial(n : number ): number [] {
274335 const fac = Array (n + 1 ).fill (1 );
275336 for (let i = 1 ; i <= n ; i ++ ) {
@@ -281,24 +342,90 @@ function factorial(n: number): number[] {
281342function reverseString(s : string ): string {
282343 return s .split (' ' ).reverse ().join (' ' );
283344}
345+ ```
284346
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 ) {
286414 const fac = factorial (n);
287415 let ans = 0 ;
288- const vis = new Set < string > ();
416+ const vis = new Set ();
289417 const base = Math .pow (10 , Math .floor ((n - 1 ) / 2 ));
290418
291419 for (let i = base; i < base * 10 ; i++ ) {
292- let s = i . toString ( );
420+ let s = String (i );
293421 const rev = reverseString (s);
294422 if (n % 2 === 1 ) {
295423 s += rev .substring (1 );
296424 } else {
297425 s += rev;
298426 }
299427
300- const num = parseInt (s , 10 );
301- if (num % k !== 0 ) {
428+ if (parseInt (s, 10 ) % k !== 0 ) {
302429 continue ;
303430 }
304431
@@ -313,7 +440,7 @@ function countGoodIntegers(n: number, k: number): number {
313440
314441 const cnt = Array (10 ).fill (0 );
315442 for (const c of t) {
316- cnt [+ c ]++ ;
443+ cnt[parseInt (c, 10 ) ]++ ;
317444 }
318445
319446 let res = (n - cnt[0 ]) * fac[n - 1 ];
@@ -324,6 +451,18 @@ function countGoodIntegers(n: number, k: number): number {
324451 }
325452
326453 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 (' ' );
327466}
328467```
329468
0 commit comments