@@ -123,7 +123,15 @@ tags:
123123
124124<!-- solution:start -->
125125
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|$ 为字母表的大小。
127135
128136<!-- tabs:start -->
129137
@@ -251,13 +259,195 @@ class Solution {
251259#### C++
252260
253261``` 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+ }
254318
319+ return ans;
320+ }
321+ };
255322```
256323
257324#### Go
258325
259326```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 ;
260396
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+ }
261451```
262452
263453<!-- tabs:end -->
0 commit comments