1. 程式人生 > >P1349 廣義斐波那契數列

P1349 廣義斐波那契數列

ans oid 範圍 span ive 基本 article space while

題目描述

廣義的斐波那契數列是指形如an=p*an-1+q*an-2的數列。今給定數列的兩系數p和q,以及數列的最前兩項a1和a2,另給出兩個整數n和m,試求數列的第n項an除以m的余數。

輸入輸出格式

輸入格式:

輸入包含一行6個整數。依次是p,q,a1,a2,n,m,其中在p,q,a1,a2整數範圍內,n和m在長整數範圍內。

輸出格式:

輸出包含一行一個整數,即an除以m的余數。

輸入輸出樣例

輸入樣例#1:
1 1 1 1 10 7
輸出樣例#1:
6

說明

數列第10項是55,除以7的余數為6。

Solution:

  本題基本算是一道矩陣加速模板了,直接構造一手矩陣:

  \begin{bmatrix} a2& a1\end{bmatrix} 以及中間矩陣 \begin{bmatrix} p & 1 \\ q & 0 \end{bmatrix}

代碼:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define mem(p) memset(&p,0,sizeof(p))
 5 using namespace std;
 6 ll pp,q,a1,a2,n,m;
 7 struct mat{ll a[3
][3],r,c;}; 8 il mat mul(mat x,mat y) 9 { 10 mat p; 11 mem(p); 12 for(int i=0;i<x.r;i++) 13 for(int j=0;j<y.c;j++) 14 for(int k=0;k<x.c;k++) 15 p.a[i][j]=(p.a[i][j]+x.a[i][k]*y.a[k][j])%m; 16 p.r=x.r,p.c=y.c; 17 return p; 18 } 19 il void
fast(ll k) 20 { 21 mat p,ans; 22 mem(p),mem(ans); 23 p.r=p.c=2; 24 p.a[0][0]=pp,p.a[0][1]=1,p.a[1][0]=q; 25 ans.r=1,ans.c=2; 26 ans.a[0][0]=a2,ans.a[0][1]=a1; 27 while(k) 28 { 29 if(k&1)ans=mul(ans,p); 30 k>>=1; 31 p=mul(p,p); 32 } 33 cout<<ans.a[0][0]; 34 } 35 int main() 36 { 37 ios::sync_with_stdio(0); 38 cin>>pp>>q>>a1>>a2>>n>>m; 39 if(n==1)cout<<a1%m; 40 else if(n==2)cout<<a2%m; 41 else fast(n-2); 42 return 0; 43 }

P1349 廣義斐波那契數列