矩阵乘法
205. 斐波那契
在斐波那契数列中,\(Fib_0=0,Fib_1=1,Fib_n=Fib_{n?1}+Fib_{n?2}(n>1)\)。
给定整数 \(n\),求 \(Fib_n \,mod\,10000\)。
输入格式
输入包含多组测试用例。
每个测试用例占一行,包含一个整数 \(n\)。
当输入用例 \(n=?1\) 时,表示输入终止,且该用例无需处理。
输出格式
每个测试用例输出一个整数表示结果。
每个结果占一行。
数据范围
\(0≤n≤2×10^9\)
输入样例:
0
9
999999999
1000000000
-1
输出样例:
0
34
626
6875
解题思路
矩阵乘法
首先有:\(Fib_n=Fib_{n-1}+Fib_{n-2}\),设 \(f(n)=[Fib_n,fib_{n+1}]\),\(f(n-1)=[Fib_{n-1},fib_n]\),寻找两者之间的关系:
\([Fib_n,fib_{n+1}]=[Fib_{n-1},fib_n] \times\)
设 \(A\)=,有 \(f(n)=f(n-1)\times A\),递推得:\(f(n)=f(0)\times A^n\),其中 \(f(0)=[0,1]\),配合快速幂便可解决此题~
- 时间复杂度:\(O(2^3\times logn)\)
代码
#include
using namespace std;
const int mod=10000;
int n;
void mul(int f[],int a[][2])
{
int c[2];
memset(c,0,sizeof c);
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
c[i]=(c[i]+f[j]*a[j][i])%mod;
memcpy(f,c,sizeof f);
}
void mulself(int a[][2])
{
int c[2][2];
memset(c,0,sizeof c);
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
memcpy(a,c,sizeof c);
}
int main()
{
while(scanf("%d",&n),n!=-1)
{
int f[2]={0,1},a[2][2]={{0,1},{1,1}};
for(;n;n>>=1)
{
if(n&1)mul(f,a);
mulself(a);
}
printf("%d\n",f[0]);
}
return 0;
}