Fork me on GitHub

矩阵乘法(菲波那切数)

https://www.luogu.org/problem/show?pid=1962

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define mod 1000000007
#define LL long long
using namespace std;
LL A[3][3]=
{0,0,0,
 0,1,1,
 0,1,0,};
LL n;
LL key[3][3],bak[3][3];
void pow_A_key(LL x)
{
    while(x>=2)
    {
        if(x%2==1)
        {
            bak[1][1]=key[1][1],bak[2][2]=key[2][2],bak[1][2]=key[1][2],bak[2][1]=key[2][1];
            key[1][1]=((A[1][1]*bak[1][1])%mod+(A[2][1]*bak[1][2])%mod)%mod;
            key[1][2]=((A[1][2]*bak[1][1])%mod+(A[2][2]*bak[1][2])%mod)%mod;
        }
        bak[1][1]=A[1][1],bak[2][2]=A[2][2],bak[1][2]=A[1][2],bak[2][1]=A[2][1];
        for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
        {
            A[i][j]=0;
            for(int k=1;k<=2;k++)
            {
                A[i][j]=(A[i][j]+(bak[i][k]*bak[k][j])%mod)%mod;
            }
        }
        x/=2;
    }
    bak[1][1]=key[1][1],bak[2][2]=key[2][2],bak[1][2]=key[1][2],bak[2][1]=key[2][1];
    for(int i=1;i<=2;i++)
    for(int j=1;j<=2;j++)
    {
        key[i][j]=0;
        for(int k=1;k<=2;k++)
        {
            key[i][j]=(key[i][j]+(bak[i][k]*A[k][j])%mod)%mod; 
        }
    }
}
int main()
{
    scanf("%lld",&n);
    key[1][1]=1,key[1][2]=1;
    if(n<=2){
        printf("1");
        return 0;
    }
    pow_A_key(n-2);
    printf("%lld",key[1][1]);
    return 0;
}
posted @ 2017-03-29 15:36  primes  阅读(160)  评论(0编辑  收藏  举报