HDU 2842 矩阵快速幂(模板)

HDU 2842 矩阵快速幂

题目

链接
在这里插入图片描述
根据题意推出公式: F n = F n 1 + 2 F n 2 + 1 F_n = F_{n-1} + 2*F_{n-2} +1 ,然后利用矩阵快速幂。
( F n 1 F n 2 1 ) ( 1 1 0 2 0 0 1 0 1 ) = ( F n F n 1 1 ) \begin{pmatrix}F_{n-1}&F_{n-2}&1\\\end{pmatrix} * \begin{pmatrix}1&1&0\\2&0&0\\1&0&1\end{pmatrix} = \begin{pmatrix}F_n&F_{n-1}&1\\\end{pmatrix}
由上面公式可知,初始矩阵为 ( F n 1 F n 2 1 ) \begin{pmatrix}F_{n-1}&F_{n-2}&1\\\end{pmatrix} ,幂次矩阵为 ( 1 1 0 2 0 0 1 0 1 ) \begin{pmatrix}1&1&0\\2&0&0\\1&0&1\end{pmatrix} ,可以在 O ( l o g n ) O(logn) 级别的复杂度求出 F n F_n .
代码:

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
const int mod = 200907;
typedef long long LL;

const int m_size = 3;
const int m_max = 5;
struct node
{
    LL d[m_max][m_max];
};
node matrixm(node a, node b)
{
    node ans;
    for(int i = 0; i < m_max; i++)
        for(int j = 0; j < m_max; j++)
            ans.d[i][j] = 0;
    for(int j = 0; j <m_size; j++)
        for(int k = 0; k <m_size; k++)
            ans.d[0][j] = (ans.d[0][j]+a.d[0][k]*b.d[k][j])%mod;
    return ans;
}
node matrixw(node a, node b)
{
    node ans;
    for(int i = 0; i < m_max; i++)
        for(int j = 0; j < m_max; j++)
            ans.d[i][j] = 0;
    for(int i = 0; i < m_size; i++)
        for(int j = 0; j <m_size; j++)
            for(int k = 0; k <m_size; k++)
                ans.d[i][j] = (ans.d[i][j]+a.d[k][j]*b.d[i][k])%mod;
    return ans;
}

void initres(node &res)
{
    for(int i = 0; i < m_max; i++)
        for(int j = 0; j < m_max; j++)
            res.d[i][j] = 0;
    res.d[0][0] = 1;res.d[0][1] = 1;res.d[0][2] = 0;
    res.d[1][0] = 2;res.d[1][1] = 0;res.d[1][2] = 0;
    res.d[2][0] = 1;res.d[2][1] = 0;res.d[2][2] = 1;
    return ;
}
void initans(node &ans)
{
    for(int i = 0; i < m_max; i++)
        for(int j = 0; j < m_max; j++)
            ans.d[i][j] = 0;
    ans.d[0][0] = 2;ans.d[0][1] = 1;ans.d[0][2] = 1;
    return ;
}

node ppow(node an, node re,LL k)
{
    node ans = an;
    node res = re;
    while(k)
    {
        if(k&1)
            ans = matrixm(ans, res);
        res = matrixw(res, res);
        k >>= 1;
    }
    return ans;
}
int main()
{
    LL n;
    node ans, res;
    initans(ans);
    initres(res);
    while(scanf("%lld", &n)&&n)
    {
        if(n==1)
        {
            printf("1\n");
        }
        else if(n==2)
        {
            printf("2\n");
        }
        else
        {
            node fans = ppow(ans,res,n-2);
            printf("%lld\n", fans.d[0][0]);
        }

    }
    return 0;
}
发布了27 篇原创文章 · 获赞 13 · 访问量 1710

猜你喜欢

转载自blog.csdn.net/weixin_43855330/article/details/103036575
今日推荐