斐波那契数列求法
文章目錄
- 求斐波那切數列的幾個方法:
- 經典做法:
- 遞推:
- 動態規劃
- 矩陣快速冪
- 原理:
- 代碼:
- 例題:
- 模擬過程
求斐波那切數列的幾個方法:
經典做法:
眾所周知:斐波那契數列的定義是f(n + 1) = f(n) + f(n - 1)
我們有兩種方式來實現:一個是遞歸,一個是動態規劃
遞推:
int dfs(int n) {if (n == 1)return 1;if (n == 2)return 2;return dfs01(n - 1) + dfs01(n - 2); }動態規劃
int dfs03(int n) {vec[maxn]vec[0] = 1;vec[1] = 2;int i;for (i = 2; i < n; i++){vec[i] = vec[i - 1] + vec[i - 2];}return vec[i-1]; }矩陣快速冪
經典做法只要數一大就會超時,我們可以用矩陣快速冪進行優化,能將時間復雜度降到O(logN)
(如果全位輸出斐波那契數,貌似最大能算法到93,但是如果帶mod,那就可以算很大)
常用于求第n位斐波那契數的后x位(mod 10x)
原理:
快速冪+矩陣
矩陣乘法:左矩陣的第一行乘以右矩陣的第一列(分別相乘),乘完后相加
單位矩陣: nn的矩陣 mat ( i , i )=1; 任何一個矩陣乘以單位矩陣就是它本身 n單位矩陣=n, 可以把單位矩陣等價為整數1。(單位矩陣用在矩陣快速冪中)
在斐波那契數列中:
f[n ] = 1 * f[n-1] + 1 * f [n - 2]
f[n-1] =1 * f[n-1] +0 * f [n - 2]
我們用矩陣來表示:
這就表示了斐波那契數列如何用矩陣來實現。
代碼:
#include <iostream> #include <cstddef> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int mod=10000; typedef vector<ll> vec; typedef vector<vec> mat; mat mul(mat &a,mat &b) { mat c(a.size(),vec(b[0].size())); for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { for(int k=0; k<2; k++) { c[i][j]+=a[i][k]*b[k][j]; c[i][j]%=mod; } } } return c; } mat pow(mat a,ll n) { mat res(a.size(),vec(a.size())); for(int i=0; i<a.size(); i++) res[i][i]=1;//單位矩陣; while(n) { if(n&1) res=mul(res,a); a=mul(a,a); n/=2; } return res; } ll solve(ll n) { mat a(2,vec(2)); a[0][0]=1; a[0][1]=1; a[1][0]=1; a[1][1]=0; a=pow(a,n); return a[0][1];//也可以是a[1][0]; } int main() { ll n; while(cin>>n&&n!=-1) { cout<<solve(n)<<endl; } return 0; } #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1000000007; struct matrix //定義結構體矩陣 {ll x[2][2]; } ; matrix mul(matrix a,matrix b) //矩陣乘法運算 {matrix ans;memset(ans.x,0,sizeof(ans.x));for(int i=0;i<2;i++) //三個循環表示兩個方陣相乘,可手動推寫一遍{for(int j=0;j<2;j++){for(int k=0;k<2;k++){ans.x[i][j]+=a.x[i][k]*b.x[k][j];ans.x[i][j]%=mod;}}}return ans; } matrix quickpow(matrix p,ll n) //矩陣快速冪,與快速冪道理方法相同 {matrix ans;for(int i=0;i<2;i++){for(int j=0;j<2;j++){if(i==j){ans.x[i][j]=1;} //一開始初始化他為單位陣else ans.x[i][j]=0;}}while(n)//快速冪{if(n&1){ans=mul(ans,p);}p=mul(p,p);n>>=1;}return ans; } int main() {matrix m;m={0,1,1,1}; ll n;cin>>n;ll ans1=0;matrix ans=quickpow(m,n-1);cout<<ans.x[1][1]<<endl; return 0; }例題:
POJ 3070
模擬過程
如果數很大,比如求1000的斐波那契數列,矩陣快速冪也求不出來,那咋辦?
我們可以模擬斐波那契數列數列計算的過程,斐波那契數列的定義是f(n + 1) = f(n) + f(n - 1),我們可以手寫加減,模擬進行加減運算
例題 大菲波數
H DU - 1715
總結
- 上一篇: 在线进行 PCoA 分析和相关统计检验
- 下一篇: 最大子矩阵(普通和01)