★題目描述
fibonacci 數列的遞推公式是F(n) = F(n-1) + F(n-2)(n >= 2 且 n 為整數)。
將這個遞推式改為F(n) = aF(n-1) + bF(n-2)(n >= 2 且 n 為整數)時得到的是怎樣的數列。
注意,這里我們依然令 F(0)=F(1)=1。
★輸入格式
輸入第一行三個正整數 q, a, b。
接下來有 q 行,每行一個自然數 n。
對於50%的數據,1 <= q、n <= 1000。
對於80%的數據,1 <= q、n <= 100000。
對於100%的數據,1 <= q <= 100000,1 <= n <= 1000000000,1 <= a、b <= 1000。
★輸出格式
對於操作2,輸出一個整數,表示對應的元素。
★樣例輸入
5 4 5
2
4
8
16
32
★樣例輸出
9
209
1377
182
9
★參考代碼
思路參考自共享文件
/*
可以使用遞歸或用數組+循環的方法
但是這種方法必定超時
所以必須優化,使用矩陣求法
進行公式推導:
f[n] [a b] f[n-1] [a b]^n-1 f[1]
= * = *
f[n-1] [1 0] f[n-2] [1 0] f[0]
所以核心是
[a b]^n-1
[1 0]
現在問題轉化為快速求矩陣的冪,原理如下,例如
A8 = A4*A4 = A2*A2*A4 時間降為log(n)
*/
#include<bits/stdc++.h>
using namespace std;
int q,a,b;
const int mod=2013;
class Matrix{
private:
int a11,a12,a21,a22;
public:
Matrix(){}
Matrix(int a,int b,int c,int d){
a11=a%mod;
a12=b%mod;
a21=c%mod;
a22=d%mod;
}
Matrix operator *(const Matrix &m){
return Matrix(a11*m.a11+a12*m.a21, a11*m.a12+a12*m.a22,
a21*m.a11+a22*m.a21, a21*m.a12+a22*m.a22);
}
int getRes(){
return (a11*1+a12*1)%mod;
}
};
int fib(int n){
Matrix resM(1,0,0,1); //單元矩陣
Matrix M(a,b,1,0);
while(n>0){
if(n&1) resM = resM*M;//如果n不是偶數
M=M*M;
n>>=1; //n縮小2倍
}
return resM.getRes();
}
int main(){
cin>>q>>a>>b;
int n;
while(q--){
scanf("%d",&n);
printf("%d\n",fib(n-1));
}
return 0;
}