矩陣乘法&矩陣快速冪
阿新 • • 發佈:2018-12-24
剛好在複習dp,順便把矩陣快速冪加速遞推給複習了。
首先矩陣乘法:f[i][j]=A[i][k]*B[k][j]
我們觀察斐波那契數列f[n]=f[n-1]+f[n-2],我們構造矩陣乘法
A:[ fn-2 fn-1]
B:[0 1]
[1 1]
C=A*B=[fn-1 fn-2+fn-1]=[fn-1 fn]
所以對於C[fn-1 fn],不難得出C=[f1 f2]*B^(n-2),而B是預先設定好的矩陣,於是就可以用上矩陣快速冪。
慄一、廣義斐波那契數列
Description
廣義的斐波那契數列是指形如a(n)=p*a(n-1)+q*a(n-2)的數列。今給定數列的兩係數p和q,以及數列的最前兩項a(1)和a(2),另給出兩個整數n和m,試求數列的第n項a(n)除以m的餘數。
Input
輸入包含一行6個整數。依次是p,q,a(1),a(2),n,m,其中在p,q,a(1),a(2)整數範圍內,n和m在長整數範圍內。
Output
輸出包含一行一個整數,即a(n)除以m的餘數。
Sample Input
1 1 1 1 10 7
Sample Output
6
【樣例說明】 數列第10項是55,除以7的餘數為6。
#include<bits/stdc++.h> using namespace std; #define Inc(i,L,r) for(register int i=(L);i<=(r);++i) #define Red(i,r,L) for(register int i=(r);i>=(L);--i) #define int long long int p,q,n,m,f1,f2; struct Martix{ int a[10][10]; inline void init(bool flag){//可構造單位矩陣 memset(a,0,sizeof(a)); if(flag)Inc(i,1,4)a[i][i]=1; } }; inline Martix mul(Martix a,Martix b,int I,int J,int K,int Mod){ Martix ans; ans.init(0); Inc(i,1,I)Inc(j,1,J)Inc(k,1,K)(ans.a[i][j]+=(a.a[i][k]*b.a[k][j]))%=Mod; return ans; } inline int quick_pow(int lm,int Mod){ Martix a; a.a[1][1]=0; a.a[1][2]=q; a.a[2][1]=1; a.a[2][2]=p;//構造矩陣A Martix ans; ans.init(1); while(lm){ if(lm&1)ans=mul(ans,a,2,2,2,Mod); a=mul(a,a,2,2,2,Mod); lm>>=1; } return (ans.a[1][2]*f1+ans.a[2][2]*f2)%Mod; } signed main(){ scanf("%lld%lld%lld%lld%lld%lld",&p,&q,&f1,&f2,&n,&m); if(n==1)cout<<f1%m<<"\n"; else if(n==2)cout<<f2%m<<"\n"; else cout<<quick_pow(n-2,m)<<"\n"; return 0; }
慄二、連分數
有時間再寫吧~