TIOJ 2053 . 費氏數列(Fibonacci)

想學矩陣快速冪很久了
這次終於把他刷掉啦
其實矩陣快速冪就是矩陣乘法+快速冪而已
只要轉移式符合矩陣乘法的性質就可以使用
像費氏數列中的\(F_n=F_{n-1}+F_{n-2}\)
可以推導出如下矩陣
\(\left [\begin{array}{c}F_n\\F_{n-1}\end{array}\right ]=\left [\begin{array}{cc}1&1\\1&0\end{array}\right ] \times \left [\begin{array}{c}F_{n-1}\\F_{n-2}\end{array}\right ]\)
也就是說我們的每一項都能透過前兩項矩陣乘法後得來
這時候我們就可以使用快速冪的性質在\(O(logn)\)的時間複雜度下求得\(F_n\)的值了!
以下為code
#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
using ll = long long;
#define AC ios::sync_with_stdio(0),cin.tie(0);

struct martix
{
    ll m[2][2];

    martix operator*(martix a)
    {
        martix r;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                r.m[i][j]=0;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                for(int k=0;k<2;k++)
                {
                    r.m[i][j]=(r.m[i][j]+((m[i][k]%1000000007)*(a.m[k][j]%1000000007))%1000000007)%1000000007;
                }
        return r;
    }
}mar;

martix quickpow(int n)
{
    martix r;
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            if(i==j) r.m[i][j]=1;
            else r.m[i][j]=0;
    for(;n;n>>=1)
    {
        if(n&1) r=r*mar;
        mar=mar*mar;
    }
    return r;
}

int main()
{
    AC
    ll x1,x2,a,b,n;
    cin>>x1>>x2>>a>>b>>n;
    mar.m[0][0]=b;
    mar.m[0][1]=1;
    mar.m[1][0]=a;
    mar.m[1][1]=0;
    martix r=quickpow(n-2);
    ll ans=((x1%1000000007)*(r.m[1][0]%1000000007))%1000000007;
    ans+=((x2%1000000007)*(r.m[0][0]%1000000007))%1000000007;
    ans%=1000000007;
    cout<<ans<<'\n';
}

留言

這個網誌中的熱門文章

TIOJ 1080 . A.逆序數對 (BIT解法)

ZJ d718: Waiting In Line

AtCoder Educational DP Contest E - Knapsack 2