(矩阵快速幂)解所有类似Fibonacci 的题目
Description
In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn ? 1 + Fn ? 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
An alternative formula for the Fibonacci sequence is
Given an integer n, your goal is to compute the last 4 digits of Fn.
Input
The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ n ≤ 1,000,000,000). The end-of-file is denoted by a single line containing the number ?1.
Output
For each test case, print the last four digits of Fn. If the last four digits of Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print Fn mod 10000).
Sample Input
0
9
999999999
1000000000
-1
Sample Output
0
34
626
6875
這個題是出題人好心,直接把規(guī)律給我們找出來了,那我們就只需要求那個矩陣的n次方,然后輸出a[0][1]即可
1.先說說矩陣快速冪
為了類比快速冪,我們先寫出快速冪的代碼
快速冪求x的y次方,是把y看作二進制來的,矩陣快速冪也一樣。
區(qū)別:
1.矩陣快速冪底數(shù)是矩陣,ren是矩陣
2.最終矩陣乘矩陣還是矩陣,也就是說函數(shù)返回矩陣,ans是矩陣
3.我們存答案的ans初始化應該是初等矩陣
所以涉及到矩陣的代碼我們都要改
改完之后就是這樣了
struct matrix {LL x[2][2]; }; matrix mutimatrix(matrix a,matrix b) {matrix temp; memset(temp.x,0,sizeof(temp.x)); for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++){temp.x[i][j]+=a.x[i][k]*b.x[k][j];temp.x[i][j]%=mod;}return temp; }matrix k_powmatrix(matrix a,LL n) {matrix temp;memset(temp.x,0,sizeof(temp.x));for(int i=0;i<2;i++)temp.x[i][i]=1;while(n){if(n&1)temp=mutimatrix(temp,a);a=mutimatrix(a,a);n>>=1;}return temp; }這個出題人直接把意思說的明明白白的,直接求那個矩陣的n次方就ok
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define LL long long const int mod=10000; struct matrix {LL x[2][2]; }; matrix mutimatrix(matrix a,matrix b) {matrix temp; memset(temp.x,0,sizeof(temp.x)); for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++){temp.x[i][j]+=a.x[i][k]*b.x[k][j];temp.x[i][j]%=mod;}return temp; }matrix k_powmatrix(matrix a,LL n) {matrix temp;memset(temp.x,0,sizeof(temp.x));for(int i=0;i<2;i++)temp.x[i][i]=1;while(n){if(n&1)temp=mutimatrix(temp,a);a=mutimatrix(a,a);n>>=1;}return temp; } int main() {int n;while(cin>>n ){if(n==0) {cout<<"0\n";continue;}if(n==1||n==2) {cout<<"1\n";continue;}if(n==-1) return 0;matrix st;memset(st.x,0,sizeof(st.x));st.x[0][0]=1;st.x[0][1]=1;st.x[1][0]=1;st.x[1][1]=0;st=k_powmatrix(st,n);printf("%lld\n",(st.x[0][1]+mod)%mod);} }2.如何通過矩陣快速冪解決這種遞推問題
先看普通斐波那契
參考:https://blog.csdn.net/wust_zzwh/article/details/52058209
f(n)=f(n-1)+f(n-2)
f(1)=f(2)=1
其實這個是個遞推式,那么我們只要找到他的通項,就可以求出n為任何值時候的f(n)
那這個遞推式我們看不出他是等比還是等差數(shù)列,通項也不會求,此時就需要用矩陣
因為矩陣有一個性質,一個常數(shù)矩陣乘以一個矩陣A(n),結果是矩陣B(n)
那如果A中各個元素對應于B中各個元素滿足,A(n)=B(n-1),那這個整體就是個等比數(shù)列啊
我們設an=
上面看作是q*a(n-1)=an,由等比數(shù)列通項公式得到
q^(n-1)*a1=an
現(xiàn)在q我們已經(jīng)有了,就剩找a1了,a1我們都會求,帶特殊值么,假設n=2,a2=q*a1,然后我們就求出a1了,所以之后求an就先求q^(n-1),再求q^(n-1) *a1
因為我是學過線性代數(shù)的,其實這有個大問題,矩陣的左乘右乘結果不一樣,為了方便起見,我們通項乘的次序應該和第一個遞推式的次序一樣
還有個例子
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
Given A, B, and n, you are to calculate the value of f(n).
圖片來自:https://www.cnblogs.com/Blackops/p/5468284.html
通過這一題我們明白一個事情,那就是對我們那個矩陣數(shù)列的優(yōu)化,2* 1矩陣可以寫成2* 2矩陣,這樣的話我們不用再弄一個函數(shù)去求2* 1矩陣*2*2矩陣了
還有一點,關于n那個次冪的事,這都是看a1對應的那個n是幾,根小學學的等比數(shù)列一樣一樣的。。
還有個小竅門,我們不用一上來就推f(n),可以通過f(1),f(2)推f(3),推完之后把3變成n,1變成n-2,2變成n-1,然后帶4驗證。如果是,那就是,然后繼續(xù)ok
參考代碼:
https://blog.csdn.net/elbadaernu/article/details/77899130
總結
以上是生活随笔為你收集整理的(矩阵快速幂)解所有类似Fibonacci 的题目的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java stl分解_[STL训练]寻梦
- 下一篇: c语言中闰年 日期 天数 统计出在某个特