矩阵初学

矩阵是个非常神奇的东西,矩阵+,-,*,倒置 等基本运算

然后我们能用矩阵干什么呢?

556. Fibonacci数列

(降低递推问题的时间复杂度)

题目描述

定义:f0=f1=1, fn=fn-1+fn-2(n>=2)。{fi}称为Fibonacci数列。

输入n,求fn mod q。其中1<=q<=30000。

输入描述

第一行一个数T(1<=T<=10000)。 以下T行,每行两个数,n,q(n<=10^9, 1<=q<=30000)

输出描述

文件包含T行,每行对应一个答案。

样例输入

3
6 2
7 3
7 11

样例输出

1
0
10

数据范围及提示

1<=T<=10000

n<=10^9, 1<=q<=30000

 

分析一下就是简单的 fibonacci

但普通方法是O(n)的显然不够,我们想优化

发现f[n]只和f[n-1],f[n-2]有关系

那我们就可以避免中间复杂的无用项的计算,

想想矩阵,怎么构造乘法关系让加法递推变成乘法递推

【  f[1] ,  f[2] 】*【   0  , 1          =【 f[2] , f[3] 】

                                1  , 1   】

然后数学归纳发现可以,于是快速幂

ac:但是有些地方写的有点麻烦

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
#define LL long long 
using namespace std;
template<typename T>
inline void read(T &a){
    a=0;bool b=0;char x=getchar();
    while(x<'0'||'9'<x){
        if(x=='-')b=1;
        x=getchar();
    }
    while('0'<=x&&x<='9'){
        a=(a<<1)+(a<<3)+x-'0';
        x=getchar();
    }
    if(b)a=-a;
}
char C_[50];
int TEMP;
template <typename T>
inline void write(T a){
    if(a<0){
        putchar('-');
        a=-a;
    }
    do{
        C_[++TEMP]=a%10+'0';
        a/=10;
    }while(a);
    while(TEMP)putchar(C_[TEMP--]);
}
int n,t,q;
struct Sq{
    int num[5][5],n,m;
    Sq(){
        num[1][1]=num[1][2]=num[2][1]=num[2][2]=0;
    }
    Sq operator *(const Sq &a){
        Sq ans;
        for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
        for(int k=1;k<=m;k++){
            ans.num[i][j]=(ans.num[i][j]+num[i][k]*a.num[k][j])%q; 
        }
        ans.n=ans.m=m;
        return ans; 
    }
    void Get_E(int N){
        n=m=N;
        for(int i=1;i<=N;i++)num[i][i]=1;
    }
    void F_init(){
        n=m=2;
        num[1][1]=0;
        num[1][2]=num[2][1]=num[2][2]=1;
    }
};

inline Sq quickpow(Sq a,int n){
    Sq ans;
    ans.Get_E(2);
    
    while(n){
        if(n&1)ans=ans*a; 
        a=a*a;
        n>>=1;
    }
    return ans; 
} 
int main(){
    read(t);
    while(t--){
        read(n);
        read(q);
        Sq a;
        a.F_init();
        
        Sq b=quickpow(a,n);
        write((b.num[1][1]+b.num[2][1])%q);putchar('\n'); 
    }
    return 0;
}

 

 

 

posted @ 2019-07-24 13:41  Tj1  阅读(321)  评论(0编辑  收藏  举报