题目大意
求斐波那契数列第n项mod 10000的值。其中:
1< n < 231
输入
123456789
输出
4514
矩阵乘法
一个大小为 a ∗ b a*b a∗b 的矩阵A与一个 b ∗ c b*c b∗c 的矩阵B相乘,设C = AB,则C的大小为 a ∗ c a*c a∗c,且
C [ i ] [ j ] = ∑ k = 1 b A [ i ] [ k ] ∗ B [ k ] [ j ] , 其 中 ( 1 < = i < = a , 1 < = j < = c ) C[i][j] = \sum_{k=1}^{b}A[i][k]*B[k][j] ,其中 (1<=i<=a,1<=j<=c) C[i][j]=k=1∑bA[i][k]∗B[k][j],其中(1<=i<=a,1<=j<=c)
看看这题。
F [ n ] = F [ n − 1 ] + F [ n − 2 ] F[n] = F[n-1] + F[n-2] F[n]=F[n−1]+F[n−2]
设一矩阵为 【 F [ n ] , F [ n − 1 ] 】 【F[n],F[n-1]】 【F[n],F[n−1]】
则 【 F [ n ] , F [ n − 1 ] 】 = 【 F [ n − 1 ] + F [ n − 2 ] , F [ n − 1 ] 】 【F[n],F[n-1]】=【F[n-1]+F[n-2],F[n-1]】 【F[n],F[n−1]】=【F[n−1]+F[n−2],F[n−1]】
= 【 F [ n − 1 ] , F [ n − 2 ] 】 ∗ A =【F[n-1],F[n-2]】* A =【F[n−1],F[n−2]】∗A
= 【 F [ n − 2 ] , F [ n − 3 ] 】 ∗ A 2 =【F[n-2],F[n-3]】*A^2 =【F[n−2],F[n−3]】∗A2
= . . . = ... =...
= 【 F [ 2 ] , F [ 1 ] 】 ∗ A n − 2 =【F[2],F[1]】* A^{n-2} =【F[2],F[1]】∗An−2
这个矩阵A需要我们自己列出来。
据我的理解,我的矩阵A是这样的:
意思是,
F [ n ] = ( 1 ∗ f [ n − 1 ] ) + ( 1 ∗ f [ n − 2 ] ) F[n]=(1 * f[n-1])+(1 * f[n-2]) F[n]=(1∗f[n−1])+(1∗f[n−2])
F [ n − 1 ] = ( 1 ∗ f [ n − 1 ] ) + ( 0 ∗ f [ n − 2 ] ) F[n-1]=(1 * f[n-1])+(0 * f[n-2]) F[n−1]=(1∗f[n−1])+(0∗f[n−2])
所以一个1*2的矩阵,乘上A,就可以转到下一个状态。
看回前面,
【 F [ n ] , F [ n − 1 ] 】 = 【 F [ 2 ] , F [ 1 ] 】 ∗ A n − 2 【F[n],F[n-1]】=【F[2],F[1]】* A^{n-2} 【F[n],F[n−1]】=【F[2],F[1]】∗An−2
其中 A n − 2 A^{n-2} An−2 可以用快速幂来求。
时间复杂度就优秀了起来。
代码
#include<cstdio>
int n;
struct asdf{
//定义结构体
int n,m; //行数,列数
int k[5][5]; //矩阵里的值
} A,B,C;
asdf operator *(asdf aa, asdf bb){
//定义矩阵乘法
asdf cc;
cc.n = aa.n;
cc.m = bb.m;
for(int i = 1; i <= cc.n; ++i)
for(int j = 1 ;j <= cc.m; ++j)
cc.k[i][j] = 0;
for(int i = 1; i <= cc.n; ++i) //枚举新矩阵c的每一格
for(int j = 1; j <= cc.m; ++j)
for(int l = 1; l <= aa.m; ++l) //枚举k,即A的列,B的行。
cc.k[i][j] = (cc.k[i][j] + aa.k[i][l] * bb.k[l][j]) % 10000; //相乘,累计
return cc; //返回
}
asdf ksm(int l){
//快速幂
if(l == 1) return A;
asdf ll = ksm(l/2);
if(l % 2 == 0) return ll * ll;
return ll * ll * A;
}
int main(){
scanf("%d",&n); //输入
A.n = 2; A.m = 2;
A.k[1][1] = A.k[1][2] = A.k[2][1] = 1; //初始化矩阵A
B = ksm(n-1);
printf("%d",B.k[1][1]% 10000); //输出F[n]
} ```