大致题意
就是“简单”地求一个斐波那契数列
分析
虽然这是我们熟悉的斐波那契数列,但 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;
}