Matrix beginner

Matrix is ​​a very wonderful thing, matrix +, - basic operations, *, upside down, etc.

Then we can use the matrix do it?

556. Fibonacci sequence

(Recursive problem of lower time complexity)

Title Description

Is defined: f0 = f1 = 1, fn = fn-1 + fn-2 (n> = 2). {Fi} called Fibonacci series.

Input n, find fn mod q. Where 1 <= q <= 30000.

Enter a description

A first line number T (1 <= T <= 10000). T The following lines of two numbers, n, q (n <= 10 ^ 9, 1 <= q <= 30000)

Output Description

File contains T lines, each line corresponds to an answer.

Sample input

3
6 2
7 3
7 11

Sample Output

1
0
10

Data range and tips

1<=T<=10000

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

 

Analyze is simply fibonacci

But common method is O (n) is clearly not enough, we want to optimize

Found f [n] only and f [n-1], f [n-2] has a relationship

That we can avoid the middle of complex calculations useless items,

Think of matrix multiplication how the relationship between structure allows recursive addition becomes multiplication recurrence

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

                                1  , 1   】

Then mathematical induction can be found, then quickly power

ac: But some local write a bit of trouble

#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;
}

 

 

 

Guess you like

Origin www.cnblogs.com/a-blog-of-taojiayi-2003/p/11237460.html