1. 程式人生 > >矩陣運算快速冪來快速計算線性遞推式

矩陣運算快速冪來快速計算線性遞推式

斐波那契數列
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;
}