矩陣運算快速冪來快速計算線性遞推式
阿新 • • 發佈:2018-12-18
斐波那契數列
f(0)=0; f(1)=1; f(n)=f(n-1)+f(n-2),n>1
從上面這個方程中我們可以看到很明顯的遞推關係,當n>1的時候很明顯發現會有一個關係式,但是實際上我們在做運算的時候,如果一步一步的按照遞推式計算,將會消耗大量的時間(最短也是O(n)的時間複雜度),於是我們這個時候就需要引入矩陣乘法和快速冪來減少時間複雜度
矩陣乘法:
設A為mp的矩陣,B為pn的矩陣,那麼稱m*n的矩陣C為矩陣A與B的乘積,其中矩陣C中的第i行第j列元素可以表示為A的第i行與B的第j列對應元素乘積和
矩陣相乘:矩陣相乘最重要的方法是一般矩陣乘積。它只有在第一個矩陣的列數(column)和第二個矩陣的行數(row)相同時才有意義
。一般單指矩陣乘積時,指的便是一般矩陣乘積。一個m×n的矩陣就是m×n個數排成m行n列的一個數陣。由於它把許多資料緊湊的集中到了一起,所以有時候可以簡便地表示一些複雜的模型。
設A為mp的矩陣,B為pn的矩陣,那麼稱m*n的矩陣C為矩陣A與B的乘積,記作C=AB:
首先:快速冪取模模板
例如:求x的n次冪並取模
int quickmod(long long n,long long x,long long r) //整型的
{
int ans=1;
while(n)
{
if(n&1)
ans=ans*x%r;
n>>=1;
x* =x%r;
}
return ans;
}
矩陣 (struct)來定義
struct Matrix{
int m[2][2];
}
矩陣的乘法運算
Matrix mul(Matrix k,Matrix n)
{
matrix ans;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
{
ans.m[i][j]=0;
for(int k=0;k<2;k++ )
ans.m[i][j]+=k.m[i][k]*n.m[k][j]%mod;
}
return ans;
}
兩者結合一下即可
最終程式碼
#include <iostream>
using namespace std;
const long long mod=1e9+7;
struct Matrix{
int m[2][2];
};
Matrix mul(Matrix A,Matrix B)
{
Matrix ans;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
{
ans.m[i][j]=0;
for(int k=0;k<2;k++)
ans.m[i][j]+=A.m[i][k]*B.m[k][j]%mod;
}
return ans;
}
Matrix quickmod(long long n,Matrix x)
{
Matrix ans;
ans.m[0][0]=1;
ans.m[0][1]=0;
ans.m[1][0]=0;
ans.m[1][1]=1;
while(n)
{
if(n&1)
ans=mul(ans,x);
n>>=1;
x=mul(x,x);
}
return ans;
}
int main()
{
Matrix A,ans;
int n;
cin>>n;
ans.m[0][0]=1;
ans.m[0][1]=0;
A.m[0][0]=1;
A.m[0][1]=1;
A.m[1][0]=1;
A.m[1][1]=0;
ans=mul(ans,quickmod(n-1,A));
cout<<ans.m[0][0]<<endl;
return 0;
}