题目链接:https://vjudge.net/contest/328717#problem/F
题意:
求斐波那契数列的第n项的最后四位数( 0 ≤ n ≤ 1,000,000,000),
注意对于每个测试用例,打印f[n]的最后四位数字。如果f[n]的最后四位数都是零,则打印“0”;否则,省略任何前导零(即打印f[n] mod 10000)。
引入矩阵的概念:
单位矩阵:
矩阵的左上角到右下角上的元素都为1,除此以外,矩阵中的元素全部为0。
单位矩阵*任何矩阵=矩阵的本身。
矩阵快速幂算法:
假如现在有一个n * n的方阵A。所谓方阵就是行数和列数相等的矩阵,先给出一个数M,让算矩阵A的M次幂。
struct Matrix
{
int mp[maxn][maxn];
} ans,res;
Matrix Mul( Matrix A, Matrix B)
{
Matrix temp;/*定义一个临时矩阵,存放A*B的结果*/
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
temp.mp[i][j]=0;
for(int k=1; k<=n; k++)
temp.mp[i][j]+=A.mp[i][k]*B.mp[k][j];
}
}
return temp;
}
void QuickPower(int N)
{
/*整数的快速幂ans初始化为1,
对于矩阵的乘法来说,ans应该初始化为单位矩阵,
对于单位矩阵E,任何矩阵A*E=A*/
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(i==j)
ans.mp[i][j]=1;
else
ans.mp[i][j]=0;
}
while(N)
{
if(N&1)
ans=Mul(ans,res);
res=Mul(res,res);
N=N>>1;
}
}
赋予矩阵快速幂意义:
观察f[n] = f[n-1]+f[n-2] 第n项是由第n-1项和第n-2项递推而来。
同理,第n+1项由第n项和第n-1项递推而来。
f[n-1]、f[n-2]则乘上左方矩阵,就能得到等号左侧矩阵,第一个位置
即为要求的f[n]。
完整代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
int n;
struct node
{
int mp[3][3];
} first,behid;
node solve(node x,node y)
{
node temp;
for(int i=1; i<=2; i++)
{
for(int j=1; j<=2; j++)
{
temp.mp[i][j]=0;
for(int k=1; k<=2; k++)
{
temp.mp[i][j]+=(x.mp[i][k]*y.mp[k][j]);
temp.mp[i][j]%=10000;
}
}
}
return temp;
}
int Quick_Mi(int n)
{
for(int i=1; i<=2; i++)/*初始化为单位矩阵*/
for(int j=1; j<=2; j++)
{
if(i==j)
first.mp[i][j]=1;
else
first.mp[i][j]=0;
}
behid.mp[1][1]=1;
behid.mp[1][2]=1;
behid.mp[2][1]=1;
behid.mp[2][2]=0;/*为斐波那契创造的矩阵*/
while(n)
{
if(n&1)
first=solve(first,behid);
behid=solve(behid,behid);
n>>=1;
}
return first.mp[1][2];
}
int main()
{
while(~scanf("%d",&n))
{
if(n==-1)
break;
int ans=Quick_Mi(n);
printf("%d\n",ans);
}
return 0;
}