牛客:NC14607 递推

递推(矩阵快速幂)

题目描述
题目链接

JYM和XJ转眼就从小学上了高中。在学习递推的时候,JYM在纸上随手写了一个递推关系式:an=2an-1,a0=0。写完这个递推式,JYM拿给XJ看,XJ觉得太过简单,于是大笔一挥,在等式右边又加了一个式子,变成了这样:an=2an-1+n2。JYM看到这个式子,想要算几个项来看看,可是一算就发现这个数据量太大了,你能帮他解决这个问题吗?

输入描述:
输入数据有多组(不超过100组数据),每组数据包含一个整数N<=1018

输出描述:
一个整数X,表示递推式第n项的值。由于数字太大,因此结果对于1000000009取模后输出。

示例1

输入
0
1
2
3

输出
0
1
6
21


这里通过构建T×Fn-1=Fn型关系式解答(前提知识:矩阵快速幂

根据递推式an=2*an-1+n2,写出第n项所包含的元素:an,n2
还有第n-1项的元素an-1,(n-1)2
然后考虑如何将(n-1)2转化到n2:(n-1)2+2n-1=n2,所以F矩阵中应当还有n和1这两个元素,现在罗列所有元素,形成矩阵Fn:

[ a n n 2 n 1 ] \left[ \begin{matrix} an \\ n^2 \\ n\\ 1 \end{matrix} \right] ann2n1

再列出Fn-1:
[ a n − 1 ( n − 1 ) 2 n − 1 1 ] \left[ \begin{matrix} an-1 \\ (n-1)^2 \\ n-1\\ 1 \end{matrix} \right] an1(n1)2n11

通过两者关系构建转移矩阵T
[ 2 1 2 1 0 1 2 1 0 0 1 1 0 0 0 1 ] \left[ \begin{matrix} 2 & 1 & 2 & 1\\ 0 & 1 & 2 & 1 \\ 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 \end{matrix} \right] 2000110022101111

即确定了关系式T*Fn-1=Fn中的每个元素,可通过矩阵快速幂解答

#include<iostream>
#include<cstdio>
#include<cstring>
const int MAXN=4;
const int mod=1000000009;
using namespace std;
struct zhen
{
    long long m[MAXN][MAXN];
    zhen(){memset(m,0,sizeof(m));}
};
zhen cheng(zhen a,zhen b)
{
    zhen res;
    for(int i=0;i<MAXN;++i)
        for(int j=0;j<MAXN;++j)
            for(int k=0;k<MAXN;++k)
                res.m[i][j]=(res.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
    return res;
}
zhen quick(zhen a,long long n)
{
    zhen res,base=a;
    for(int i=0;i<MAXN;++i)
        res.m[i][i]=1;
    while(n)
    {
        if(n&1)
            res=cheng(res,base);
        base=cheng(base,base);
        n>>=1;
    }
    return res;
}
int main()
{
    long long n;
    while(cin>>n)
    {
        zhen a;
        a.m[0][0]=2,a.m[0][1]=1,a.m[0][2]=2,a.m[0][3]=1;
        a.m[1][0]=0,a.m[1][1]=1,a.m[1][2]=2,a.m[1][3]=1;
        a.m[2][0]=0,a.m[2][1]=0,a.m[2][2]=1,a.m[2][3]=1;
        a.m[3][0]=0,a.m[3][1]=0,a.m[3][2]=0,a.m[3][3]=1;
        zhen c,res;
        c.m[3][0]=1;
        a=quick(a,n);
        res=cheng(a,c);
        cout<<res.m[0][0]<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值