0830-矩阵快速幂-POJ 3070

版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/82221207

传送门

大致题意

就是“简单”地求一个斐波那契数列

分析

虽然这是我们熟悉的斐波那契数列,但 n 的范围达到了1e9。所以如果单纯递推的话会超时,那么我们换一种求法

POJ 题目描述上已经给出了提示,那我们照着敲一遍代码即可

先来了解一下矩阵乘法

两个矩阵只有当左边的矩阵的列数等于右边矩阵的行数时,两个矩阵才可以进行矩阵的乘法运算 

主要方法就是:用左边矩阵的第一行,逐个乘以右边矩阵的列,第一行与第一列各个元素的乘积相加,第一行与第二列的各个元素的乘积相加。。。。

第二行也是,逐个乘以右边矩阵的列。。。。

第三行。。。

。。。。

最后得出结果

所以说如果一个 m * s 的 A 矩阵乘以一个 s * n 的 B 矩阵,最后得出来的就是 m * n  的矩阵,如图解释

然后知道了这点,我们再回顾一下一般的整数快速幂,乱搞一下,把一般的乘法换做矩阵的乘法,就可以啦

只是需要注意一点:在整数快速幂的时候我们ans是1,这样是为了保证第一次乘的时候值不变,那么转到矩阵快速幂来说,我们把 ans 初始成一个单位矩阵,这样无论第一次的时候ans乘以什么,最后的值都是原来的那个

所谓单位矩阵,就是一个从左上角到右下角对角线上的值都为1,其余都为0的矩阵

代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#define mod 10000
using namespace std;
struct matrix{
	int m[4][4];
}ans,res;
matrix mul(matrix a,matrix b,int n){
	matrix temp;
	int i,j,k;
	for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
			temp.m[i][j]=0;
	for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
			for(k=1;k<=n;++k)
				temp.m[i][j]=(temp.m[i][j]+1ll*a.m[i][k]*b.m[k][j])%mod;//因为最后只取4位我们就直接对10000取模
	return temp;
}
void quickpower(int N,int n){
	int i,j,k;
	for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
		{
			if(i==j) ans.m[i][j]=1;
			else ans.m[i][j]=0;
		}	//初始为单位矩阵
	while(N){
		if(N&1)    ans=mul(ans,res,n);
		res=mul(res,res,n);
		N=N>>1;
	}
}
int main(){
	int hh;
	scanf("%d",&hh);
	while(hh!=-1){
		res.m[1][1]=1;res.m[1][2]=1;
		res.m[2][1]=1;res.m[2][2]=0;
		quickpower(hh,2);
		printf("%d\n",ans.m[1][2]);
		scanf("%d",&hh);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/82221207