矩阵构造+矩阵快速幂-HDU5950

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5950
题意:

给出公式f(n)=f(n-1)+f(n-2)*2+n^4
给出n f[1] f[2] 求f[n]

分析:

快速幂
把公式分解一下,求一下矩阵,矩阵快速幂搞一下就好

题目的难点在于矩阵的构造

题解:

典型的矩阵快速幂的运用。关键是i^4怎么维护?我们可以当成求第i+1项,那么i^4就变成了(i+1)^4。那么这时我们可以用二项式定理从i^4、i^3、i^2、i^1、i^0的组合中得到(i+1)^4。也就是说总共需要维护:f[i+1]、f[i]、(i+1)^4、(i+1)^3、(i+1)^2、(i+1)^1、(i+1)^0。矩阵如下:
这里写图片描述
这里写图片描述

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <vector>
#define ll long long
#define ull unsigned long long
using namespace std;
const ll mod=2147493647;

struct Mat
{
    ll mat[7][7];
    void init()
    {
        for(int i=0; i<7; i++)
            for(int j=0; j<7; j++)
                mat[i][j]=(i==j);//对矩阵初始化的函数
    }
};
Mat multi(Mat x,Mat y)
{
    Mat ans;
    for(int i=0; i<7; i++)
        for(int j=0; j<7; j++)
        {
            ans.mat[i][j]=0;
            for(int k=0; k<7; k++)
                ans.mat[i][j]=(ans.mat[i][j]+x.mat[i][k]*y.mat[k][j]%mod)%mod;
        }
    return ans;
}
Mat quick_matrix_pow(Mat x,ll n)
{
    Mat ans;
    ans.init();//矩阵快速幂中ans进行初始化
    while(n)
    {
        if(n&1)
            ans=multi(ans,x);
        n>>=1;
        x=multi(x,x);
    }
    return ans;
}
Mat p = {   1, 2, 1, 4, 6, 4, 1,
            1, 0, 0, 0, 0, 0, 0,
            0, 0, 1, 4, 6, 4, 1,
            0, 0, 0, 1, 3, 3, 1,
            0, 0, 0, 0, 1, 2, 1,
            0, 0, 0, 0, 0, 1, 1,
            0, 0, 0, 0,0, 0, 1
        };//构造出来的矩阵
int main()
{
    int t;
    ll n,a,b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%I64d%I64d%I64d",&n,&a,&b);
        if(n==1)
            printf("%I64d\n",a);
        else if(n==2)
            printf("%I64d\n",b);
        else
        {
            Mat x=p;
            x=quick_matrix_pow(x,n-2);
            ll ans=0;
            ans=(ans+b*x.mat[0][0])%mod;
            ans=(ans+a*x.mat[0][1])%mod;
            ans=(ans+16*x.mat[0][2])%mod;
            ans=(ans+8*x.mat[0][3])%mod;
            ans=(ans+4*x.mat[0][4])%mod;
            ans=(ans+2*x.mat[0][5])%mod;
            ans=(ans+x.mat[0][6])%mod;
            printf("%I64d\n",ans);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值