@@ -123,7 +123,15 @@ tags:
123
123
124
124
<!-- solution:start -->
125
125
126
- ### 方法一
126
+ ### 方法一:矩阵快速幂加速递推
127
+
128
+ 我们定义 $f[ i] [ j ] $ 表示经过 $i$ 次转换后,字母表中第 $j$ 个字母的个数。初始时 $f[ 0] [ j ] $ 为字符串 $s$ 中字母表中第 $j$ 个字母的个数。
129
+
130
+ 由于每一次转换后第 $j$ 个字母的个数,都跟下一次转换有关,转换的次数 $t$ 较大,我们可以使用矩阵快速幂,来加速整个递推过程。
131
+
132
+ 注意,答案可能非常大,我们需要对 $10^9 + 7$ 取模。
133
+
134
+ 时间复杂度 $O(n + \log t \times |\Sigma|^3)$,空间复杂度 $O(|\Sigma|^2)$。其中 $|\Sigma|$ 为字母表的大小。
127
135
128
136
<!-- tabs:start -->
129
137
@@ -251,13 +259,195 @@ class Solution {
251
259
#### C++
252
260
253
261
``` cpp
262
+ class Solution {
263
+ public:
264
+ static constexpr int MOD = 1e9 + 7;
265
+ static constexpr int M = 26;
266
+
267
+ using Matrix = vector<vector<int>>;
268
+
269
+ Matrix matmul(const Matrix& a, const Matrix& b) {
270
+ int n = a.size(), p = b.size(), q = b[0].size();
271
+ Matrix res(n, vector<int>(q, 0));
272
+ for (int i = 0; i < n; ++i) {
273
+ for (int k = 0; k < p; ++k) {
274
+ if (a[i][k]) {
275
+ for (int j = 0; j < q; ++j) {
276
+ res[i][j] = (res[i][j] + 1LL * a[i][k] * b[k][j] % MOD) % MOD;
277
+ }
278
+ }
279
+ }
280
+ }
281
+ return res;
282
+ }
283
+
284
+ Matrix matpow (Matrix mat, int power) {
285
+ Matrix res(M, vector<int >(M, 0));
286
+ for (int i = 0; i < M; ++i) res[ i] [ i ] = 1;
287
+ while (power) {
288
+ if (power % 2) res = matmul(res, mat);
289
+ mat = matmul(mat, mat);
290
+ power /= 2;
291
+ }
292
+ return res;
293
+ }
294
+
295
+ int lengthAfterTransformations(string s, int t, vector<int>& nums) {
296
+ vector<int> cnt(M, 0);
297
+ for (char c : s) {
298
+ cnt[c - 'a']++;
299
+ }
300
+
301
+ Matrix matrix(M, vector<int>(M, 0));
302
+ for (int i = 0; i < M; ++i) {
303
+ for (int j = 1; j <= nums[i]; ++j) {
304
+ matrix[i][(i + j) % M] = 1;
305
+ }
306
+ }
307
+
308
+ Matrix cntMat(1, vector<int>(M));
309
+ for (int i = 0; i < M; ++i) cntMat[0][i] = cnt[i];
310
+
311
+ Matrix factor = matpow(matrix, t);
312
+ Matrix result = matmul(cntMat, factor);
313
+
314
+ int ans = 0;
315
+ for (int x : result[0]) {
316
+ ans = (ans + x) % MOD;
317
+ }
254
318
319
+ return ans;
320
+ }
321
+ };
255
322
```
256
323
257
324
#### Go
258
325
259
326
```go
327
+ func lengthAfterTransformations(s string, t int, nums []int) int {
328
+ const MOD = 1e9 + 7
329
+ const M = 26
330
+
331
+ cnt := make([]int, M)
332
+ for _, c := range s {
333
+ cnt[int(c-'a')]++
334
+ }
335
+
336
+ matrix := make([][]int, M)
337
+ for i := 0; i < M; i++ {
338
+ matrix[i] = make([]int, M)
339
+ for j := 1; j <= nums[i]; j++ {
340
+ matrix[i][(i+j)%M] = 1
341
+ }
342
+ }
343
+
344
+ matmul := func(a, b [][]int) [][]int {
345
+ n, p, q := len(a), len(b), len(b[0])
346
+ res := make([][]int, n)
347
+ for i := 0; i < n; i++ {
348
+ res[i] = make([]int, q)
349
+ for k := 0; k < p; k++ {
350
+ if a[i][k] != 0 {
351
+ for j := 0; j < q; j++ {
352
+ res[i][j] = (res[i][j] + a[i][k]*b[k][j]%MOD) % MOD
353
+ }
354
+ }
355
+ }
356
+ }
357
+ return res
358
+ }
359
+
360
+ matpow := func(mat [][]int, power int) [][]int {
361
+ res := make([][]int, M)
362
+ for i := 0; i < M; i++ {
363
+ res[i] = make([]int, M)
364
+ res[i][i] = 1
365
+ }
366
+ for power > 0 {
367
+ if power%2 == 1 {
368
+ res = matmul(res, mat)
369
+ }
370
+ mat = matmul(mat, mat)
371
+ power /= 2
372
+ }
373
+ return res
374
+ }
375
+
376
+ cntMat := [][]int{make([]int, M)}
377
+ copy(cntMat[0], cnt)
378
+
379
+ factor := matpow(matrix, t)
380
+ result := matmul(cntMat, factor)
381
+
382
+ ans := 0
383
+ for _, v := range result[0] {
384
+ ans = (ans + v) % MOD
385
+ }
386
+ return ans
387
+ }
388
+ ```
389
+
390
+ #### TypeScript
391
+
392
+ ``` ts
393
+ function lengthAfterTransformations(s : string , t : number , nums : number []): number {
394
+ const MOD = BigInt (1e9 + 7 );
395
+ const M = 26 ;
260
396
397
+ const cnt: number [] = Array (M ).fill (0 );
398
+ for (const c of s ) {
399
+ cnt [c .charCodeAt (0 ) - ' a' .charCodeAt (0 )]++ ;
400
+ }
401
+
402
+ const matrix: number [][] = Array .from ({ length: M }, () => Array (M ).fill (0 ));
403
+ for (let i = 0 ; i < M ; i ++ ) {
404
+ for (let j = 1 ; j <= nums [i ]; j ++ ) {
405
+ matrix [i ][(i + j ) % M ] = 1 ;
406
+ }
407
+ }
408
+
409
+ const matmul = (a : number [][], b : number [][]): number [][] => {
410
+ const n = a .length ,
411
+ p = b .length ,
412
+ q = b [0 ].length ;
413
+ const res: number [][] = Array .from ({ length: n }, () => Array (q ).fill (0 ));
414
+ for (let i = 0 ; i < n ; i ++ ) {
415
+ for (let k = 0 ; k < p ; k ++ ) {
416
+ const aik = BigInt (a [i ][k ]);
417
+ if (aik !== BigInt (0 )) {
418
+ for (let j = 0 ; j < q ; j ++ ) {
419
+ const product = aik * BigInt (b [k ][j ]);
420
+ const sum = BigInt (res [i ][j ]) + product ;
421
+ res [i ][j ] = Number (sum % MOD );
422
+ }
423
+ }
424
+ }
425
+ }
426
+ return res ;
427
+ };
428
+
429
+ const matpow = (mat : number [][], power : number ): number [][] => {
430
+ let res: number [][] = Array .from ({ length: M }, (_ , i ) =>
431
+ Array .from ({ length: M }, (_ , j ) => (i === j ? 1 : 0 )),
432
+ );
433
+ while (power > 0 ) {
434
+ if (power % 2 === 1 ) res = matmul (res , mat );
435
+ mat = matmul (mat , mat );
436
+ power = Math .floor (power / 2 );
437
+ }
438
+ return res ;
439
+ };
440
+
441
+ const cntMat: number [][] = [cnt .slice ()];
442
+ const factor = matpow (matrix , t );
443
+ const result = matmul (cntMat , factor );
444
+
445
+ let ans = 0n ;
446
+ for (const v of result [0 ]) {
447
+ ans = (ans + BigInt (v )) % MOD ;
448
+ }
449
+ return Number (ans );
450
+ }
261
451
```
262
452
263
453
<!-- tabs:end -->
0 commit comments