常规解法:动态规划
dp[n]表示楼梯阶数为n时有多少种上楼方案 状态转移方程dp[n]=dp[n-1]+dp[n-2] 边界条件:dp[1]=1 dp[2]=2
矩阵快速幂
利用矩阵推导出递推关系,即构造出一个矩阵的n次方乘一个列向量得到一个列向量,此时就可以通过矩阵的n次幂来得到目标列向量(该列向量包含所要求的f(n))
递推式子:
f
(
n
)
=
f
(
n
?
1
)
+
f
(
n
?
2
)
f(n) = f(n-1) + f(n-2)
f(n)=f(n?1)+f(n?2) 利用矩阵构造递推关系:
[
1
1
1
0
]
?
[
f
(
n
)
f
(
n
?
1
)
]
=
[
f
(
n
)
?
f
(
n
?
1
)
f
(
n
)
]
\left[ \begin{matrix} 1 & 1\\ 1 & 0 \\ \end{matrix} \right]*\left[ \begin{matrix} f(n) \\ f(n-1) \\ \end{matrix} \right]=\left[ \begin{matrix} f(n)*f(n-1)\\ f(n) \\ \end{matrix} \right]
[11?10?]?[f(n)f(n?1)?]=[f(n)?f(n?1)f(n)?] 由于
[
f
(
n
)
?
f
(
n
?
1
)
f
(
n
)
]
=
[
f
(
n
+
1
)
f
(
n
)
]
\left[ \begin{matrix} f(n)*f(n-1)\\ f(n) \\ \end{matrix} \right]=\left[ \begin{matrix} f(n+1)\\ f(n) \\ \end{matrix} \right]
[f(n)?f(n?1)f(n)?]=[f(n+1)f(n)?] 进而得出
[
1
1
1
0
]
?
[
f
(
n
)
f
(
n
?
1
)
]
=
[
f
(
n
+
1
)
f
(
n
)
]
\left[ \begin{matrix} 1 & 1\\ 1 & 0 \\ \end{matrix} \right]*\left[ \begin{matrix} f(n) \\ f(n-1) \\ \end{matrix} \right]=\left[ \begin{matrix} f(n+1)\\ f(n) \\ \end{matrix} \right]
[11?10?]?[f(n)f(n?1)?]=[f(n+1)f(n)?] 最终的递推关系为:
[
1
1
1
0
]
n
?
[
f
(
1
)
f
(
0
)
]
=
[
f
(
n
+
1
)
f
(
n
)
]
\left[ \begin{matrix} 1 & 1\\ 1 & 0 \\ \end{matrix} \right]^n*\left[ \begin{matrix} f(1) \\ f(0) \\ \end{matrix} \right]=\left[ \begin{matrix} f(n+1)\\ f(n) \\ \end{matrix} \right]
[11?10?]n?[f(1)f(0)?]=[f(n+1)f(n)?]
令
[
1
1
1
0
]
=
M
令 \left[ \begin{matrix} 1 & 1\\ 1 & 0 \\ \end{matrix} \right]=M
令[11?10?]=M
此时我们只需要快速的求出
M
n
M^n
Mn即可得出
f
(
n
)
f(n)
f(n)
假
设
M
n
=
[
C
00
C
01
C
10
C
11
]
假设M^n= \left[ \begin{matrix} C_{00}&C_{01}\\ C_{10}&C_{11}\\ \end{matrix} \right]
假设Mn=[C00?C10??C01?C11??] 最终答案
f
(
n
)
=
C
00
∣
∣
C
10
+
C
11
f(n)= C_{00}||C_{10}+C_{11}
f(n)=C00?∣∣C10?+C11?
矩阵快速幂题型重点在于
- 找到递推关系
- 利用离散化快速求解矩阵M的幂次方
代码如下:
vector<vector<long long>> multiply(vector<vector<long long>>& a,vector<vector<long long >>b){
vector<vector<long long>> c(2,vector<long long >(2));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++){
c[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j];
}
return c;
}
vector<vector<long long>> pow(vector<vector<long long>>& a,int n){
vector<vector<long long>> ret={{1,0},{0,1}};
while(n>0){
if(n&1)
ret=multiply(ret,a);
n>>=1;
a=multiply(a,a);
}
return ret;
}
int climbStairs(int n) {
vector<vector<long long>> ret ={{1,1},{1,0}};
vector<vector<long long>> res=pow(ret,n);
return res[0][0];
}
|