斐波那契(矩阵乘法&&快速幂)

在斐波那契数列中,Fib0=0,Fib1=1,Fibn=Fibn−1+Fibn−2(n>1)Fib0=0,Fib1=1,Fibn=Fibn−1+Fibn−2(n>1)。

给定整数n,求Fibnmod10000Fibnmod10000。

输入格式

输入包含多组测试用例。

每个测试用例占一行,包含一个整数n。

当输入用例n=-1时,表示输入终止,且该用例无需处理。

输出格式

每个测试用例输出一个整数表示结果。

每个结果占一行。

数据范围

0≤n≤2∗109

输入样例:

0
9
999999999
1000000000
-1

输出样例:

0
34
626
6875

 思路:由于n的范围达到了1e9,所以就算递推o(n)的做法也无法满足时间的要求,所以这里用到了矩阵乘法,就是把这种递推的运算用一个递推矩阵参与的矩阵乘法模拟,因为矩阵可以一次存储多个数字,所以极大的减少了计算的状态,简单地说,这里就是用一个矩阵a[2][2]初始等于={{0,1},{1,1}},a就是递推矩阵,让f[2]={0,1},(fib数列的前两个数),所以f[0]=fib(n),f[1]=fib(n+1),让f右乘一个a后,相当于:

f[0]=0*fib(n)+1*fib(n+1)=fib(n+1)

f[1]=1*fib(n)+1*fib(n+1)=fib(n+2)

这样f就变为了下一状态,f[0]=fib(n+1),f[1]=fib(n+2),以此类推,最终f[0]的结果即为答案。

注:矩阵相乘时,可用快速幂的方法优化,具体见代码。

#include <iostream>
#include <cstring>
#define int long long 
using namespace std;

const int mod=1e4;

int n;

void mul(int f[2],int a[2][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 c);
}

void mulself(int a[2][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 qmi(int n)
{
    int f[2]={0,1};
    int a[2][2]={{0,1},{1,1}};
    while(n){
        if(n&1) mul(f,a);
        mulself(a);
        n>>=1;
    }
    return f[0];
}

signed main()
{
    while(cin>>n,n!=-1){
        cout<<qmi(n)<<endl;
    }
    return 0;
}
发布了176 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Mr_Kingk/article/details/105498491
今日推荐