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