习题:M斐波那契数列(矩阵优化)

题目

传送门

思路

首先可以很容易的发现

\(f(n)=a^x*b^y\)

之后我们根据函数的定义单独考虑\(f(n)\)是a的多少次幂乘上b的多少次幂

然后我们很容易的发现,

\(f(n)\)这个函数其实就是对指数进行了\(g_n=g_{n-1}+g_{n-2}\)

也就是斐波拉契数列

之后可以自然而然地想到矩阵的优化

但是这里要注意,虽然a和b的加速矩阵是一样的

但是他们的初始矩阵却是不一样的

因为\(f(0)==a\)\(f(1)==b\)的情况

另外当mod是质数的时候,\(\varphi(mod)=mod-1\)

而且进行矩阵快速幂的时候的模数与最后算答案的模数是不一样的

代码

#include<iostream>
#include<cstring>
using namespace std;
const long long mod=1e9+6;
const long long modd=1e9+7;
struct mat
{
    long long n;
    long long m;
    long long a[5][5];
    mat()
    {
        n=0;
        m=0;
        memset(a,0,sizeof(a));
    }
    friend mat operator * (const mat &a,const mat &b) 
    {
        mat t;
        t.n=a.n;
        t.m=b.m;
        for(int i=1;i<=a.n;i++)
        {
            for(int j=1;j<=b.m;j++)
            {
                for(int k=1;k<=a.m;k++)
                {
                    t.a[i][j]=(t.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
                }
            }
        }
        return t;
    }
};
long long varphi(long long n)
{
    long long ans=n;
    for(int i=2;1ll*i*i<=n;i++)
    {
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(!(n%i))
                n/=i;
        }
    }
    if(n>1)
        ans=ans/n*(n-1);
    return ans;
}
mat qkpow(mat a,long long b)
{
    if(b==1)
        return a;
    mat t=qkpow(a,b/2);
    t=(t*t);
    if(b%2==1)
        t=(t*a);
    return t;
}
long long qkpow(long long a,long long b)
{
    if(b==0)
        return 1;
    if(b==1)
        return a;
    long long t=qkpow(a,b/2);
    t=(t*t)%modd;
    if(b%2==1)
        t=(t*a)%modd;
    return t;
}
long long a,b,n;
mat t1;
mat t2;
mat acc;
void init()
{
    acc.n=acc.m=4;
    acc.a[1][2]=acc.a[2][1]=acc.a[2][2]=1;
    acc.a[1][1]=0;
}
int main()
{
    while(cin>>a>>b>>n)
    {
        if(n==0)
        {
            cout<<a<<'\n';
            continue;
        }
        if(n==1)
        {
            cout<<b<<'\n';
            continue;
        }
        t1.n=t2.n=1;
        t1.m=t2.m=2;
        t1.a[1][1]=t2.a[1][2]=1;
        t1.a[1][2]=t2.a[1][1]=0;
        init();
        t1=t1*qkpow(acc,n-1);
        init();
        t2=t2*qkpow(acc,n-1);
        //cout<<t1.a[1][2]<<' '<<t2.a[1][2]<<'\n';
        cout<<qkpow(a%modd,t1.a[1][2])*qkpow(b%modd,t2.a[1][2])%modd<<'\n';
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/loney-s/p/11922599.html