1. 程式人生 > >模板C++ 02數論算法 4矩陣乘法

模板C++ 02數論算法 4矩陣乘法

矩陣 快速冪 行數 正方形 eof str memset isp images

矩陣乘法:用來求某種 遞推關系。

矩陣相乘只有在第一個矩陣的列數和第二個矩陣的行數相同時才有意義

定義

A為A*M的矩陣,B為M*B的矩陣,那麽矩陣C為矩陣AB的乘積,其中矩陣C中的第i行第j列元素可以表示為:

技術分享

如下所示:

技術分享

開一個2*2的矩陣:主要是為了快速冪的方便,一個可以和自己乘上許多次(>=2)的矩陣只有可能是正方形的,所以要開這樣一個矩陣。

【題目描述】

a[1]=a[2]=a[3]=1

a[x]=a[x-3]+a[x-1] (x>3)

求a數列的第n項對1000000007(10^9+7)取余的值。

【輸入格式】

第一行一個整數T,表示詢問個數。

以下T行,每行一個正整數n。

【輸出格式】

每行輸出一個非負整數表示答案。

【樣例輸入】3 6 8 10

【樣例輸出】4 9 19

【數據範圍】對於100%的數據 T<=100,n<=2*10^9;

然後就是使用矩陣乘法來遞推。

如果想要預處理,也是可以的,只不過T<=100,所以偷懶省空間。

struct mod
{
    long long a[4][4];
    mod() { memset(a,0,sizeof(a)); }
};
mod mul(mod a,mod b)//矩陣乘法
{
    mod c;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            
for(int k=1;k<=3;k++) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%1000000007; return c; } void make(int n) { mod a,c; c.a[1][1]=1;c.a[2][1]=1;c.a[3][1]=1; a.a[1][1]=0;a.a[1][2]=1;a.a[1][3]=0; a.a[2][1]=0;a.a[2][2]=0;a.a[2][3]=1; a.a[3][1]=1;a.a[3][2]=0;a.a[3][3]=1; n++;
while(n>0)//快速冪 { if(n&1) c=mul(c,a);//不能是mul(a,c) a=mul(a,a);//(A^n)*B n>>=1; } printf("%d\n",c.a[3][3]%1000000007); } int main(int argc,char *argv[]) { int t;scanf("%d",&t); while(t--) { int n; scanf("%d",&n); make(n); } }

模板C++ 02數論算法 4矩陣乘法