题目
题目描述 Description
定义:f0=f1=1, fn=fn-1+fn-2(n>=2)。{fi}称为Fibonacci数列。
输入n,求fn mod q。其中1<=q<=30000。
输入描述 Input Description
第一行一个数T(1<=T<=10000)。
以下T行,每行两个数,n,q(n<=109, 1<=q<=30000)
输出描述 Output Description
文件包含T行,每行对应一个答案。
样例输入 Sample Input
3
6 2
7 3
7 11
样例输出 Sample Output
1
0
10
数据范围及提示 Data Size & Hint
1<=T<=10000
n<=109, 1<=q<=30000
代码
//By Chorolop
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int m;
struct M{
int mat[5][5];
void INIT(){
memset(mat,0,sizeof(mat));
}
M operator * (M B) const{
M C;
for(int i = 1;i <= 2;i++){
for(int j = 1;j <= 2;j++){
C.mat[i][j] = 0;
for(int k = 1;k <= 2;k++)
C.mat[i][j] = (C.mat[i][j]+mat[i][k]*B.mat[k][j]);
C.mat[i][j] %= m;
}
}
return C;
}
};
M ksm(M A,int n){
M B = A;
while(n){
if(n&1)
B = B * A;
A = A*A;
n >>= 1;
}
return B;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int q;
scanf("%d%d",&q,&m);
M A;
A.mat[1][1] = A.mat[1][2] = A.mat[2][1] = 1;
A.mat[2][2] = 0;
A = ksm(A,q-2);
printf("%d\n",(A.mat[1][1]+A.mat[1][2])%m);
}
return 0;
}
评价
这道题其实只能算入门题,用于理解“矩阵优化递推式”的。
对于这道题我们有f(n) = f(n-1) + f(n-2),那其实可以看作f(n) = 1 * f(n-1) + 1 * f(n-2),再联系矩阵乘法的过程就能猜想出目标矩阵了,然后运用快速幂算法合并计算需要的矩阵表达式。
理论基础
矩阵乘法+快速幂