题目## 题目
解题思路
这是一个斐波那契数列的变种问题,使用矩阵快速幂来解决。关键点:
-
递推关系:
- f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n−1)+f(n−2)
- 可以使用矩阵快速幂优化时间复杂度
-
矩阵转换:
- 使用 2 × 2 2\times 2 2×2 矩阵进行状态转移
- 注意矩阵下标从 1 1 1 开始
-
取模运算:
- 所有运算都需要取模,防止溢出
- mod = 1000000007
代码
class GoUpstairs {
public:
#define i64 long long
const int mod = 1e9+7;
vector<vector<i64>> ksm_mar(vector<vector<i64>>A, vector<vector<i64>>B) {
vector<vector<i64>>C(3, vector<i64>(3, 0));
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 2; j++) {
for(int k = 1; k <= 2; k++) {
C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
}
}
}
return C;
}
vector<vector<i64>> cul(vector<vector<i64>>A, vector<vector<i64>>B) {
vector<vector<i64>>C(3, vector<i64>(3, 0));
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 1; j++) {
for(int k = 1; k <= 2; k++) {
C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
}
}
}
return C;
}
int countWays(int n) {
if(n == 0) return 1;
vector<vector<i64>>A(3, vector<i64>(3, 0));
A[1][2] = 1;
A[2][1] = 1;
A[2][2] = 1;
vector<vector<i64>>ans(3, vector<i64>(3, 0));
ans[1][1] = 1;
ans[2][1] = 2;
n--;
while(n) {
if(n & 1) ans = cul(A, ans);
A = ksm_mar(A, A);
n >>= 1;
}
return ans[1][1];
}
};
import java.util.*;
public class GoUpstairs {
private static final int mod = 1000000007;
private long[][] ksm_mar(long[][] A, long[][] B) {
long[][] C = new long[3][3];
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 2; j++) {
for(int k = 1; k <= 2; k++) {
C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
}
}
}
return C;
}
private long[][] cul(long[][] A, long[][] B) {
long[][] C = new long[3][3];
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 1; j++) {
for(int k = 1; k <= 2; k++) {
C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
}
}
}
return C;
}
public int countWays(int n) {
if(n == 0) return 1;
long[][] A = new long[3][3];
A[1][2] = 1;
A[2][1] = 1;
A[2][2] = 1;
long[][] ans = new long[3][3];
ans[1][1] = 1;
ans[2][1] = 2;
n--;
while(n > 0) {
if((n & 1) == 1) ans = cul(A, ans);
A = ksm_mar(A, A);
n >>= 1;
}
return (int)ans[1][1];
}
}
class GoUpstairs:
def ksm_mar(self, A, B):
mod = 1000000007
C = [[0 for i in xrange(3)] for i in xrange(3)]
for i in xrange(1, 3):
for j in xrange(1, 3):
for k in xrange(1, 3):
C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod
return C
def cul(self, A, B):
mod = 1000000007
C = [[0 for i in xrange(3)] for i in xrange(3)]
for i in xrange(1, 3):
for j in xrange(1, 2):
for k in xrange(1, 3):
C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod
return C
def countWays(self, n):
if n == 0:
return 1
mod = 1000000007
A = [[0 for i in xrange(3)] for i in xrange(3)]
A[1][2] = 1
A[2][1] = 1
A[2][2] = 1
ans = [[0 for i in xrange(3)] for i in xrange(3)]
ans[1][1] = 1
ans[2][1] = 2
n -= 1
while n:
if n & 1:
ans = self.cul(A, ans)
A = self.ksm_mar(A, A)
n >>= 1
return ans[1][1]
算法及复杂度
- 算法:矩阵快速幂
- 时间复杂度: O ( log n ) \mathcal{O(\log n)} O(logn),使用快速幂优化
- 空间复杂度: O ( 1 ) \mathcal{O(1)} O(1),只使用了常数额外空间
解题思路
这是一个斐波那契数列变种问题。关键点:
-
递推关系:
- f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n−1)+f(n−2)
- 到达第 n n n 级的方法 = 从 n − 1 n-1 n−1 级跨1步 + 从 n − 2 n-2 n−2 级跨2步
-
数组存储:
- 直接初始化数组的前三个值:[0,1,2]
- 从第四个值开始递推计算
-
取模运算:
- 每次计算时都进行取模,防止溢出
- m o d = 1000000007 mod = 1000000007 mod=1000000007
代码
class GoUpstairs {
public:
int countWays(int n) {
vector<int> d(n);
d[0] = 0;
d[1] = 1;
d[2] = 2;
for(int i = 3; i < n; i++) {
d[i] = (d[i-1] % 1000000007 + d[i-2] % 1000000007) % 1000000007;
}
return d[n-1];
}
};
import java.util.*;
public class GoUpstairs {
public int countWays(int n) {
// write code here
int[] d = new int[n];
d[0] = 0;
d[1] = 1;
d[2] = 2;
for(int i = 3; i < n; i++) {
d[i] = (int)(((long)d[i-1] % 1000000007 + d[i-2] % 1000000007) % 1000000007);
}
return d[n-1];
}
}
# -*- coding:utf-8 -*-
class GoUpstairs:
def countWays(self, n):
d = [0] * n
d[0] = 0
d[1] = 1
d[2] = 2
for i in xrange(3, n):
d[i] = (d[i-1] % 1000000007 + d[i-2] % 1000000007) % 1000000007
return d[n-1]
算法及复杂度
- 算法:动态规划(使用数组存储)
- 时间复杂度: O ( n ) \mathcal{O(n)} O(n),需要遍历到第 n n n项
- 空间复杂度: O ( n ) \mathcal{O(n)} O(n),需要数组存储所有中间结果
校招算法题:斐波那契变种求解

被折叠的 条评论
为什么被折叠?



