矩阵乘法


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;
}