斐波那契数列(数论+矩阵加速)

斐波那契数列

输入一个long long范围的一个数x,要求输出斐波那契数列第x项。

思路

显然这个题目,用O(N)的朴素做法是肯定不行的。所以我们要寻求一种新的方法。
接下来介绍一种计算:矩阵加法。这样的一种运算具有满足结合律的性质。对这个有兴趣的同学可以参阅人教版数学选修4-2的第一章和第二章(第一章带你入门,第二章教你矩阵乘法)。
大概矩阵加速就是和快速幂类似的,下面代码里面的操作可以教会我们其实结构体类型是可以取等并相互转移的。
这个东西不知道就不会做,知道了就会做,然后大概这种东西还是背下来快速幂之后就可以类比了。

代码

#include
#include
#include
#include
#include
#include
using namespace std;
long long i,j,k,m,n;


struct data
{
    long long arr[4][4];
}a,b;

long long r()
{
    long long aans=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        aans*=10;
        aans+=ch-'0';
        ch=getchar();
    }
    return aans*f;
}

data mul(data aa,data bb)
{
    data cc;
    memset(cc.arr,0,sizeof(cc.arr));
    for(i=1;i<=2;i++)
    for(j=1;j<=2;j++)
    for(k=1;k<=2;k++)
    cc.arr[i][j]+=(aa.arr[i][k]*bb.arr[k][j])%1000000007;
    return cc;
}

data ksm(long long x)
{
    data c,d;
    long long xx=x;
    c=(data){{{},{0,0,1},{0,1,1}}};
    d=(data){{{},{0,1,0},{0,0,1}}};
    if(xx==1)
    return c;

    while(x)
    {
        if(x&1!=0)
        d=mul(d,c);
        c=mul(c,c);
        x>>=1;
    }
    return d;
}



int main()
{
    n=r();
    a=(data){{{},{0,1,1},{0,0,0}}};
    b=(data){{{},{0,0,1},{0,1,1}}};
    a=mul(a,ksm(n-1));
    cout<1][1]%1000000007;
}
/*
100000000000000000
*/

斐波那契数列(数论+矩阵加速)_第1张图片

你可能感兴趣的:(数论,#,矩阵加速)