[bsoj2258] 线性递推式


题目描述

  动态规划的实现形式之一是递推,因此递推在OI中十分重要。在某信息学的分支学科中,LC学会了如何求一阶线性递推数列。由于他想在正在学习主干学科,因此希望知道求出N阶线性递推数列。为此,他了解到了以下的内容:
一个N阶线性递推式是这样的式子:
  这里写图片描述
  也就是说,这个数列的每一项都是由他之前连续N项相加所得。其中还包括一个常数An。
  例如,当N=2,A0=A1=1,A2=0时,这个式子就是我们熟悉的斐波那契数列。当然,作为边界条件,F0、F1……Fn-1都是已知的。
  LC对这如何去求这个式子一筹莫展,因此请你来帮助他。你的任务就是对于一个给定的N阶线性递推式,求出它的第K项是多少。


输入格式

  第一行两个整数:N,K,其中N表示这个式子是N阶线性递推式,K表示你需要求得那一项。
  第二行有N+1个整数:A0,A1,…,An,表示这个递推式的系数。
  第三行有N个整数:F0,F1,….,Fn-1,表示数列的初始值。


输出格式

只有一行,其中只有一个整数,表示这个数列第K项的值。由于数据较大,你只需输出结果 mod 9973的值。


样例数据

样例输入

2 10
1 1 0
0 1

样例输出

55


说明

对于50%的数据:N<=K<=10^6
对于100%的数据:1〈N〈=10
N<=K<=10^18
1<=Ai,Fi<=10^4
这里写图片描述


题目分析

这题调起来要死人。。。
[FkFk1...Fkn+101]=[Fn1Fn2...F001]A0A1A2...An10An100...000010...000001...001.....................000...100000...001


源代码

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const long long Get_Int() {
    long long num=0,bj=1;
    char x=getchar();
    while(x<'0'||x>'9') {
        if(x=='-')bj=-1;
        x=getchar();
    }
    while(x>='0'&&x<='9') {
        num=num*10+x-'0';
        x=getchar();
    }
    return num*bj;
}
typedef long long LL;
const int maxn=15,mod=9973;
struct Matrix {
    LL n,m,a[maxn][maxn];
    Matrix(LL n,LL m) {
        this->n=n;
        this->m=m;
        memset(a,0,sizeof(a));
    }
    Matrix(LL n,LL m,char E) { //单位矩阵
        this->n=n;
        this->m=m;
        memset(a,0,sizeof(a));
        for(int i=1; i<=n; i++)a[i][i]=1;
    }
    void init(LL n,LL m) {
        this->n=n;
        this->m=m;
        memset(a,0,sizeof(a));
    }
    LL* operator [] (const LL x) {
        return a[x];
    }
    Matrix operator = (Matrix b) {
        init(b.n,b.m);
        for(int i=1; i<=b.n; i++)
            for(int j=1; j<=b.m; j++)
                a[i][j]=b[i][j];
    }
    Matrix operator + (Matrix& b) {
        for(int i=1; i<=b.n; i++)
            for(int j=1; j<=b.m; j++)
                a[i][j]+=b[i][j];
    }
    void operator += (Matrix& b) {
        *this=*this+b;
    }
    Matrix operator - (Matrix& b) {
        for(int i=1; i<=b.n; i++)
            for(int j=1; j<=b.m; j++)
                a[i][j]-=b[i][j];
    }
    void operator -= (Matrix& b) {
        *this=*this-b;
    }
    Matrix operator * (LL k) {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                a[i][j]*=k;
    }
    void operator *= (LL k) {
        *this=*this*k;
    }
    Matrix operator * (Matrix& b) {
        Matrix c(n,b.m);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=b.m; j++)
                for(int k=1; k<=m; k++)
                    c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
        return c;
    }
    void operator *= (Matrix& b) {
        *this=*this*b;
    }
    Matrix operator ^ (LL b) {
        Matrix ans(n,m,'e'),a=*this;
        while(b>0) {
            if(b&1)ans=ans*a;
            a*=a;
            b>>=1;
        }
        return ans;
    }
    void Output() {
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=m; j++)
                printf("%lld ",a[i][j]);
            putchar('\n');
        }
    }
};
LL n,k; 
int main() {
    n=Get_Int();
    k=Get_Int();
    Matrix a(1,n+2),b(n+5,n+2); //初始矩阵及系数矩阵 
    for(int i=n; i>=1; i--)b[i][1]=Get_Int();
    a[1][n+2]=1;
    b[n+2][1]=Get_Int();
    for(int i=1; i<=n; i++)b[i][i+1]=1;
    b[n+2][n+2]=1;
    for(int i=n; i>=1; i--)a[1][i]=Get_Int();
    Matrix tmp=b^(k-n+1);
    printf("%lld\n",(a*tmp)[1][1]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值