diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/README.md b/solution/1100-1199/1137.N-th Tribonacci Number/README.md index ea83a7d85786b..11781282dd15d 100644 --- a/solution/1100-1199/1137.N-th Tribonacci Number/README.md +++ b/solution/1100-1199/1137.N-th Tribonacci Number/README.md @@ -52,6 +52,32 @@ T_4 = 1 + 1 + 2 = 4 时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为给定的整数。 +**方法二:矩阵快速幂加速递推** + +我们设 $Tib(n)$ 表示一个 $1 \times 3$ 的矩阵 $\begin{bmatrix} T_n & T_{n - 1} & T_{n - 2} \end{bmatrix}$,其中 $T_n$, $T_{n - 1}$ 和 $T_{n - 2}$ 分别表示第 $n$ 个、第 $n - 1$ 个和第 $n - 2$ 个泰波那契数。 + +我们希望根据 $Tib(n-1) = \begin{bmatrix} T_{n - 1} & T_{n - 2} & T_{n - 3} \end{bmatrix}$ 推出 $Tib(n)$。也即是说,我们需要一个矩阵 $base$,使得 $Tib(n - 1) \times base = Tib(n)$,即: + +$$ +\begin{bmatrix} +T_{n - 1} & T_{n - 2} & T_{n - 3} +\end{bmatrix} \times base = \begin{bmatrix} T_n & T_{n - 1} & T_{n - 2} \end{bmatrix} +$$ + +由于 $T_n = T_{n - 1} + T_{n - 2} + T_{n - 3}$,所以矩阵 $base$ 为: + +$$ +\begin{bmatrix} + 1 & 1 & 0 \\ + 1 & 0 & 1 \\ + 1 & 0 & 0 +\end{bmatrix} +$$ + +我们定义初始矩阵 $res = \begin{bmatrix} 1 & 1 & 0 \end{bmatrix}$,那么 $T_n$ 等于 $res$ 乘以 $base^{n - 3}$ 的结果矩阵中所有元素之和。使用矩阵快速幂求解即可。 + +时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。 + ### **Python3** @@ -67,6 +93,35 @@ class Solution: return a ``` +```python +class Solution: + def tribonacci(self, n: int) -> int: + def mul(a: List[List[int]], b: List[List[int]]) -> List[List[int]]: + m, n = len(a), len(b[0]) + c = [[0] * n for _ in range(m)] + for i in range(m): + for j in range(n): + for k in range(len(a[0])): + c[i][j] = c[i][j] + a[i][k] * b[k][j] + return c + + def pow(a: List[List[int]], n: int) -> List[List[int]]: + res = [[1, 1, 0]] + while n: + if n & 1: + res = mul(res, a) + n >>= 1 + a = mul(a, a) + return res + + if n == 0: + return 0 + if n < 3: + return 1 + a = [[1, 1, 0], [1, 0, 1], [1, 0, 0]] + return sum(pow(a, n - 3)[0]) +``` + ### **Java** @@ -86,6 +141,51 @@ class Solution { } ``` +```java +class Solution { + public int tribonacci(int n) { + if (n == 0) { + return 0; + } + if (n < 3) { + return 1; + } + int[][] a = {{1, 1, 0}, {1, 0, 1}, {1, 0, 0}}; + int[][] res = pow(a, n - 3); + int ans = 0; + for (int x : res[0]) { + ans += x; + } + return ans; + } + + private int[][] mul(int[][] a, int[][] b) { + int m = a.length, n = b[0].length; + int[][] c = new int[m][n]; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; + } + + private int[][] pow(int[][] a, int n) { + int[][] res = {{1, 1, 0}}; + while (n > 0) { + if ((n & 1) == 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; + } +} +``` + ### **C++** ```cpp @@ -104,6 +204,50 @@ public: }; ``` +```cpp +class Solution { +public: + int tribonacci(int n) { + if (n == 0) { + return 0; + } + if (n < 3) { + return 1; + } + vector> a = {{1, 1, 0}, {1, 0, 1}, {1, 0, 0}}; + vector> res = pow(a, n - 3); + return accumulate(res[0].begin(), res[0].end(), 0); + } + +private: + using ll = long long; + vector> mul(vector>& a, vector>& b) { + int m = a.size(), n = b[0].size(); + vector> c(m, vector(n)); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < b.size(); ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; + } + + vector> pow(vector>& a, int n) { + vector> res = {{1, 1, 0}}; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; + } +}; +``` + ### **Go** ```go @@ -116,6 +260,51 @@ func tribonacci(n int) int { } ``` +```go +func tribonacci(n int) (ans int) { + if n == 0 { + return 0 + } + if n < 3 { + return 1 + } + a := [][]int{{1, 1, 0}, {1, 0, 1}, {1, 0, 0}} + res := pow(a, n-3) + for _, x := range res[0] { + ans += x + } + return +} + +func mul(a, b [][]int) [][]int { + m, n := len(a), len(b[0]) + c := make([][]int, m) + for i := range c { + c[i] = make([]int, n) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + for k := 0; k < len(b); k++ { + c[i][j] += a[i][k] * b[k][j] + } + } + } + return c +} + +func pow(a [][]int, n int) [][]int { + res := [][]int{{1, 1, 0}} + for n > 0 { + if n&1 == 1 { + res = mul(res, a) + } + a = mul(a, a) + n >>= 1 + } + return res +} +``` + ### **JavaScript** ```js @@ -137,6 +326,96 @@ var tribonacci = function (n) { }; ``` +```js +/** + * @param {number} n + * @return {number} + */ +var tribonacci = function (n) { + if (n === 0) { + return 0; + } + if (n < 3) { + return 1; + } + const a = [ + [1, 1, 0], + [1, 0, 1], + [1, 0, 0], + ]; + return pow(a, n - 3)[0].reduce((a, b) => a + b); +}; + +function mul(a, b) { + const [m, n] = [a.length, b[0].length]; + const c = Array.from({ length: m }, () => Array.from({ length: n }, () => 0)); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + for (let k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; +} + +function pow(a, n) { + let res = [[1, 1, 0]]; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; +} +``` + +### **TypeScript** + +```ts +function tribonacci(n: number): number { + if (n === 0) { + return 0; + } + if (n < 3) { + return 1; + } + const a = [ + [1, 1, 0], + [1, 0, 1], + [1, 0, 0], + ]; + return pow(a, n - 3)[0].reduce((a, b) => a + b); +} + +function mul(a: number[][], b: number[][]): number[][] { + const [m, n] = [a.length, b[0].length]; + const c = Array.from({ length: m }, () => Array.from({ length: n }, () => 0)); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + for (let k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; +} + +function pow(a: number[][], n: number): number[][] { + let res = [[1, 1, 0]]; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; +} +``` + ### **PHP** ```php diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/README_EN.md b/solution/1100-1199/1137.N-th Tribonacci Number/README_EN.md index 1ba1b3d37f702..86e38756d8593 100644 --- a/solution/1100-1199/1137.N-th Tribonacci Number/README_EN.md +++ b/solution/1100-1199/1137.N-th Tribonacci Number/README_EN.md @@ -51,6 +51,35 @@ class Solution: return a ``` +```python +class Solution: + def tribonacci(self, n: int) -> int: + def mul(a: List[List[int]], b: List[List[int]]) -> List[List[int]]: + m, n = len(a), len(b[0]) + c = [[0] * n for _ in range(m)] + for i in range(m): + for j in range(n): + for k in range(len(a[0])): + c[i][j] = c[i][j] + a[i][k] * b[k][j] + return c + + def pow(a: List[List[int]], n: int) -> List[List[int]]: + res = [[1, 1, 0]] + while n: + if n & 1: + res = mul(res, a) + n >>= 1 + a = mul(a, a) + return res + + if n == 0: + return 0 + if n < 3: + return 1 + a = [[1, 1, 0], [1, 0, 1], [1, 0, 0]] + return sum(pow(a, n - 3)[0]) +``` + ### **Java** ```java @@ -68,6 +97,51 @@ class Solution { } ``` +```java +class Solution { + public int tribonacci(int n) { + if (n == 0) { + return 0; + } + if (n < 3) { + return 1; + } + int[][] a = {{1, 1, 0}, {1, 0, 1}, {1, 0, 0}}; + int[][] res = pow(a, n - 3); + int ans = 0; + for (int x : res[0]) { + ans += x; + } + return ans; + } + + private int[][] mul(int[][] a, int[][] b) { + int m = a.length, n = b[0].length; + int[][] c = new int[m][n]; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; + } + + private int[][] pow(int[][] a, int n) { + int[][] res = {{1, 1, 0}}; + while (n > 0) { + if ((n & 1) == 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; + } +} +``` + ### **C++** ```cpp @@ -86,6 +160,50 @@ public: }; ``` +```cpp +class Solution { +public: + int tribonacci(int n) { + if (n == 0) { + return 0; + } + if (n < 3) { + return 1; + } + vector> a = {{1, 1, 0}, {1, 0, 1}, {1, 0, 0}}; + vector> res = pow(a, n - 3); + return accumulate(res[0].begin(), res[0].end(), 0); + } + +private: + using ll = long long; + vector> mul(vector>& a, vector>& b) { + int m = a.size(), n = b[0].size(); + vector> c(m, vector(n)); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < b.size(); ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; + } + + vector> pow(vector>& a, int n) { + vector> res = {{1, 1, 0}}; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; + } +}; +``` + ### **Go** ```go @@ -98,6 +216,51 @@ func tribonacci(n int) int { } ``` +```go +func tribonacci(n int) (ans int) { + if n == 0 { + return 0 + } + if n < 3 { + return 1 + } + a := [][]int{{1, 1, 0}, {1, 0, 1}, {1, 0, 0}} + res := pow(a, n-3) + for _, x := range res[0] { + ans += x + } + return +} + +func mul(a, b [][]int) [][]int { + m, n := len(a), len(b[0]) + c := make([][]int, m) + for i := range c { + c[i] = make([]int, n) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + for k := 0; k < len(b); k++ { + c[i][j] += a[i][k] * b[k][j] + } + } + } + return c +} + +func pow(a [][]int, n int) [][]int { + res := [][]int{{1, 1, 0}} + for n > 0 { + if n&1 == 1 { + res = mul(res, a) + } + a = mul(a, a) + n >>= 1 + } + return res +} +``` + ### **JavaScript** ```js @@ -119,6 +282,96 @@ var tribonacci = function (n) { }; ``` +```js +/** + * @param {number} n + * @return {number} + */ +var tribonacci = function (n) { + if (n === 0) { + return 0; + } + if (n < 3) { + return 1; + } + const a = [ + [1, 1, 0], + [1, 0, 1], + [1, 0, 0], + ]; + return pow(a, n - 3)[0].reduce((a, b) => a + b); +}; + +function mul(a, b) { + const [m, n] = [a.length, b[0].length]; + const c = Array.from({ length: m }, () => Array.from({ length: n }, () => 0)); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + for (let k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; +} + +function pow(a, n) { + let res = [[1, 1, 0]]; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; +} +``` + +### **TypeScript** + +```ts +function tribonacci(n: number): number { + if (n === 0) { + return 0; + } + if (n < 3) { + return 1; + } + const a = [ + [1, 1, 0], + [1, 0, 1], + [1, 0, 0], + ]; + return pow(a, n - 3)[0].reduce((a, b) => a + b); +} + +function mul(a: number[][], b: number[][]): number[][] { + const [m, n] = [a.length, b[0].length]; + const c = Array.from({ length: m }, () => Array.from({ length: n }, () => 0)); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + for (let k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; +} + +function pow(a: number[][], n: number): number[][] { + let res = [[1, 1, 0]]; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; +} +``` + ### **PHP** ```php diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.cpp b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.cpp index 03324e8183c79..28a2cbfccf3d1 100644 --- a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.cpp +++ b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.cpp @@ -1,13 +1,41 @@ -class Solution { -public: - int tribonacci(int n) { - long long a = 0, b = 1, c = 1; - while (n--) { - long long d = a + b + c; - a = b; - b = c; - c = d; - } - return (int) a; - } +class Solution { +public: + int tribonacci(int n) { + if (n == 0) { + return 0; + } + if (n < 3) { + return 1; + } + vector> a = {{1, 1, 0}, {1, 0, 1}, {1, 0, 0}}; + vector> res = pow(a, n - 3); + return accumulate(res[0].begin(), res[0].end(), 0); + } + +private: + using ll = long long; + vector> mul(vector>& a, vector>& b) { + int m = a.size(), n = b[0].size(); + vector> c(m, vector(n)); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < b.size(); ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; + } + + vector> pow(vector>& a, int n) { + vector> res = {{1, 1, 0}}; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; + } }; \ No newline at end of file diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.go b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.go index 63382cb825179..0679ce8462987 100644 --- a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.go +++ b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.go @@ -1,7 +1,42 @@ -func tribonacci(n int) int { - a, b, c := 0, 1, 1 - for i := 0; i < n; i++ { - a, b, c = b, c, a+b+c +func tribonacci(n int) (ans int) { + if n == 0 { + return 0 } - return a + if n < 3 { + return 1 + } + a := [][]int{{1, 1, 0}, {1, 0, 1}, {1, 0, 0}} + res := pow(a, n-3) + for _, x := range res[0] { + ans += x + } + return +} + +func mul(a, b [][]int) [][]int { + m, n := len(a), len(b[0]) + c := make([][]int, m) + for i := range c { + c[i] = make([]int, n) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + for k := 0; k < len(b); k++ { + c[i][j] += a[i][k] * b[k][j] + } + } + } + return c +} + +func pow(a [][]int, n int) [][]int { + res := [][]int{{1, 1, 0}} + for n > 0 { + if n&1 == 1 { + res = mul(res, a) + } + a = mul(a, a) + n >>= 1 + } + return res } \ No newline at end of file diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.java b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.java index 8a35e2b1d8849..816c33ab7a2ae 100644 --- a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.java +++ b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.java @@ -1,12 +1,42 @@ -class Solution { - public int tribonacci(int n) { - int a = 0, b = 1, c = 1; - while (n-- > 0) { - int d = a + b + c; - a = b; - b = c; - c = d; - } - return a; - } +class Solution { + public int tribonacci(int n) { + if (n == 0) { + return 0; + } + if (n < 3) { + return 1; + } + int[][] a = {{1, 1, 0}, {1, 0, 1}, {1, 0, 0}}; + int[][] res = pow(a, n - 3); + int ans = 0; + for (int x : res[0]) { + ans += x; + } + return ans; + } + + private int[][] mul(int[][] a, int[][] b) { + int m = a.length, n = b[0].length; + int[][] c = new int[m][n]; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; + } + + private int[][] pow(int[][] a, int n) { + int[][] res = {{1, 1, 0}}; + while (n > 0) { + if ((n & 1) == 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; + } } \ No newline at end of file diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.js b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.js index 8af290bb9d571..ec4768040079f 100644 --- a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.js +++ b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.js @@ -3,14 +3,41 @@ * @return {number} */ var tribonacci = function (n) { - let a = 0; - let b = 1; - let c = 1; - while (n--) { - let d = a + b + c; - a = b; - b = c; - c = d; + if (n === 0) { + return 0; } - return a; + if (n < 3) { + return 1; + } + const a = [ + [1, 1, 0], + [1, 0, 1], + [1, 0, 0], + ]; + return pow(a, n - 3)[0].reduce((a, b) => a + b); }; + +function mul(a, b) { + const [m, n] = [a.length, b[0].length]; + const c = Array.from({ length: m }, () => Array.from({ length: n }, () => 0)); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + for (let k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; +} + +function pow(a, n) { + let res = [[1, 1, 0]]; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; +} diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.py b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.py index a3938c3a74409..fa734873e6ecb 100644 --- a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.py +++ b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.py @@ -1,6 +1,26 @@ -class Solution: - def tribonacci(self, n: int) -> int: - a, b, c = 0, 1, 1 - for _ in range(n): - a, b, c = b, c, a + b + c - return a +class Solution: + def tribonacci(self, n: int) -> int: + def mul(a: List[List[int]], b: List[List[int]]) -> List[List[int]]: + m, n = len(a), len(b[0]) + c = [[0] * n for _ in range(m)] + for i in range(m): + for j in range(n): + for k in range(len(a[0])): + c[i][j] = c[i][j] + a[i][k] * b[k][j] + return c + + def pow(a: List[List[int]], n: int) -> List[List[int]]: + res = [[1, 1, 0]] + while n: + if n & 1: + res = mul(res, a) + n >>= 1 + a = mul(a, a) + return res + + if n == 0: + return 0 + if n < 3: + return 1 + a = [[1, 1, 0], [1, 0, 1], [1, 0, 0]] + return sum(pow(a, n - 3)[0]) diff --git a/solution/1100-1199/1137.N-th Tribonacci Number/Solution.ts b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.ts new file mode 100644 index 0000000000000..d65d17f3418c4 --- /dev/null +++ b/solution/1100-1199/1137.N-th Tribonacci Number/Solution.ts @@ -0,0 +1,39 @@ +function tribonacci(n: number): number { + if (n === 0) { + return 0; + } + if (n < 3) { + return 1; + } + const a = [ + [1, 1, 0], + [1, 0, 1], + [1, 0, 0], + ]; + return pow(a, n - 3)[0].reduce((a, b) => a + b); +} + +function mul(a: number[][], b: number[][]): number[][] { + const [m, n] = [a.length, b[0].length]; + const c = Array.from({ length: m }, () => Array.from({ length: n }, () => 0)); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + for (let k = 0; k < b.length; ++k) { + c[i][j] += a[i][k] * b[k][j]; + } + } + } + return c; +} + +function pow(a: number[][], n: number): number[][] { + let res = [[1, 1, 0]]; + while (n) { + if (n & 1) { + res = mul(res, a); + } + a = mul(a, a); + n >>= 1; + } + return res; +}