【矩阵乘法】【模板】裴波拉契数列II

题目大意

求斐波那契数列第n项mod 10000的值。其中:
1< n < 231

输入

123456789

输出

4514


矩阵乘法

一个大小为 a ∗ b a*b ab 的矩阵A与一个 b ∗ c b*c bc 的矩阵B相乘,设C = AB,则C的大小为 a ∗ c a*c ac,且
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=1bA[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[n1]+F[n2]


设一矩阵为 【 F [ n ] , F [ n − 1 ] 】 【F[n],F[n-1]】 F[n],F[n1]

【 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[n1]=F[n1]+F[n2],F[n1]
= 【 F [ n − 1 ] , F [ n − 2 ] 】 ∗ A =【F[n-1],F[n-2]】* A =F[n1],F[n2]A
= 【 F [ n − 2 ] , F [ n − 3 ] 】 ∗ A 2 =【F[n-2],F[n-3]】*A^2 =F[n2],F[n3]A2
= . . . = ... =...
= 【 F [ 2 ] , F [ 1 ] 】 ∗ A n − 2 =【F[2],F[1]】* A^{n-2} =F[2],F[1]An2

这个矩阵A需要我们自己列出来。


据我的理解,我的矩阵A是这样的:
在这里插入图片描述
意思是,

F [ n ] = ( 1 ∗ f [ n − 1 ] ) + ( 1 ∗ f [ n − 2 ] ) F[n]=(1 * f[n-1])+(1 * f[n-2]) F[n]=(1f[n1])+(1f[n2])
F [ n − 1 ] = ( 1 ∗ f [ n − 1 ] ) + ( 0 ∗ f [ n − 2 ] ) F[n-1]=(1 * f[n-1])+(0 * f[n-2]) F[n1]=(1f[n1])+(0f[n2])

所以一个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[n1]=F[2],F[1]An2
其中 A n − 2 A^{n-2} An2 可以用快速幂来求。
时间复杂度就优秀了起来。


代码

#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]
} ```
 
 

猜你喜欢

转载自blog.csdn.net/qq_42937087/article/details/111064056
今日推荐