要不是考到了,我还没发现这玩意我不是很会……


# 前置

  • 多项式取模;
  • 矩阵快速幂。

# 常系数齐次线性递推

描述的是这么一个问题,给定数列 \(c_1,c_2,\dots,c_k\) 以及数列 \(f\) 的前 \(k\) 项 \(f_0,f_1,\dots,f_{k-1}\),已知 \(f\) 有如下递推公式:

\[\begin{aligned}
(n\ge m)&&f_{n}=\sum_{i=1}^kc_if_{n-i}
\end{aligned}
\]

求 \(f_n \bmod 998244353\),其中 \(n\) 可以很大,\(k\) 是 \(10^5\) 左右的数。

  • 常系数:递推式的系数 \(c_i\) 均为常数;
  • 齐次:这意味着递推式没有常数项(如果有常数项就别想了);
  • 线性:\(f_i\) 的指数都为 \(1\)。

# 算法原理

对于这种系数为常数的问题,我们有一个通用的解法 —— 矩阵快速幂:

\[\begin{bmatrix}f_{n}\\f_{n + 1}\\\vdots\\f_{n + k - 1}\end{bmatrix}=\begin{bmatrix}0&1&0&\cdots&0\\0&0&1&\cdots&0\\0&0&0&\cdots&0\\\vdots&\vdots&\vdots&\ddots&\vdots\\c_k&c_{k - 1}&c_{k - 2}&\cdots&c_1\end{bmatrix}\times\begin{bmatrix}f_{n - 1}\\f_{n}\\\vdots\\f_{n + k - 2}\end{bmatrix}
\]

记最后那个 \(k\times k\) 的转移方阵为 \(A\),初始列向量为 \(St\)。常规的计算方法即计算

\[A^n\times St
\]

复杂度 \(\mathcal O(k^3\log n)\),主要的瓶颈在于矩阵乘法。

下面要介绍的算法给出了这样一种构造,其中 \(\{c_i\}\) 是针对 \(A^n\)(注意不仅与 \(A\) 有关,还与指数 \(n\) 有关)构造的数列 ——

\[\begin{aligned}
&A^n=\sum_{i=0}^{k-1}c_iA^i\\
&A^n\times St=\sum_{i=0}^{k-1}c_iA^i\times St
\end{aligned}
\]

目前看来好像没有什么茄子用,仍然需要计算矩乘。但是我们真的需要 \(A^n\times St\) 这整个向量吗?实际上我们只需要 \(f_n\),即 \(A^n\times St\) 的第一项。

再看看这个式子就可以发现它的用处了:

\[(A^n\times St)_1=\sum_{i=0}^{k-1}(c_iA^i\times St)_1=\sum_{i=0}^{k-1}c_i(A^i\times St)_1
\]

\(A^i\times St\) 的实际意义是将 \(St\) 转移 \(i\) 次。所以 \((A^i\times St)_1=f_i\),也即

\[f_n=\sum_{i=0}^{k-1}c_if_i
\]

这样就免去了矩乘。

这就是这个算法的全部内容了?还剩下一个问题,\(\{c_i\}\) 怎么构造?

定义函数 \(C(x)\) 如下,则要求 \(C(A)=A^n\)。

\[C(x)=\sum_{i=0}^{k - 1}c_ix^i
\]

接下来是一些魔法……如果我们有函数 \(F(x)\) 满足

\[F(A)=\sum_{i=0}^{k}f_iA^i=0
\]

且有 \(G(x)\) 满足:

\[x^n=G(x)F(x)+C(x)\to C(x)=x^n\bmod F(x)
\]

易得

\[A^n=G(A)F(A)+C(A)=C(A)
\]

利用多项式取模对快速幂稍加改造就可以计算 \(C(x)\)。

「稍 加 改 造」

说起来倒也简单,把多项式 $x$ 拿来做快速幂,对 $F(x)$ 取模。

然后我们发现又需要构造 \(F(x)\)……如果要对一个一般的方阵求 \(F(A)=0\) 那确实很难,但常系数齐次线性递推的转移矩阵 \(A\) 因为它的结构特殊,有一个简洁的构造:

  • \(f_k=1\);
  • \(f_{i}=-c_{k-i}\)(\(0\le i\lt k\))。

至于为什么这样构造,就涉及到矩阵的特征向量的内容,和这个算法本身没有太紧的关联。有兴趣的读者可以参考 shadowice1984 的洛谷博客


THE END

Thanks for reading!

我也曾 隐约想过 从这世界逃离

因为有无数次 和最优解失之交臂

那时耀眼的自己 定不会轻易容许

骄傲变得同墙角霉菌 不差毫厘

——《我也曾想过一了百了(中文填词)》 By 洛天依

> Link 我也曾想过一了百了 - Bilibili

「NOTE」常系数齐次线性递推的更多相关文章

  1. 常系数齐次线性递推 & 拉格朗日插值

    常系数齐次线性递推 具体记在笔记本上了,以后可能补照片,这里稍微写一下,主要贴代码. 概述 形式: \[ h_n = a_1 h_{n-1}+a_2h_{n-2}+...+a_kh_{n-k} \] ...

  2. 【Luogu4723】线性递推(常系数齐次线性递推)

    [Luogu4723]线性递推(常系数齐次线性递推) 题面 洛谷 题解 板子题QwQ,注意多项式除法那里每个多项式的系数,调了一天. #include<iostream> #include ...

  3. 【BZOJ4161】Shlw loves matrixI (常系数齐次线性递推)

    [BZOJ4161]Shlw loves matrixI (常系数齐次线性递推) 题面 BZOJ 题解 \(k\)很小,可以直接暴力多项式乘法和取模. 然后就是常系数齐次线性递推那套理论了,戳这里 # ...

  4. 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)

    这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...

  5. 【瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)

    [背诵瞎讲] Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18) 看CSP看到一题"线性递推式",不会做,去问了问zsy怎么做,他并 ...

  6. BZOJ4161 常系数齐次线性递推

    问了数竞的毛毛搞了一番也没太明白,好在代码蛮好写先记下吧. #include<bits/stdc++.h> using namespace std; ,mod=1e9+; int n,k, ...

  7. Re.常系数齐次递推

    前言 嗯   我之前的不知道多少天看这个的时候到底在干什么呢 为什么那么..  可能大佬们太强的缘故 最后仔细想想思路那么的emmm 不说了  要落泪了 唔唔唔 前置 多项式求逆 多项式除法/取模 常 ...

  8. 【BZOJ4944】[NOI2017]泳池(线性常系数齐次递推,动态规划)

    [BZOJ4944][NOI2017]泳池(线性常系数齐次递推,动态规划) 首先恰好为\(k\)很不好算,变为至少或者至多计算然后考虑容斥. 如果是至少的话,我们依然很难处理最大面积这个东西.所以考虑 ...

  9. 2019牛客暑期多校训练营(第五场)- B generator 1 (齐次线性递推+矩阵快速幂)

    题目链接:https://ac.nowcoder.com/acm/contest/885/B 题意:已知齐次线性式xn=a*xn-1+b*xn-2,已知a,b,x0,x1,求xn,n很大,n<= ...

  10. 线性齐次递推式快速求第n项 学习笔记

    定义 若数列 \(\{a_i\}\) 满足 \(a_n=\sum_{i=1}^kf_i \times a_{n-i}\) ,则该数列为 k 阶齐次线性递推数列 可以利用多项式的知识做到 \(O(k\l ...

随机推荐

  1. 【RTOS】RTOS汇编入门 (1)

    引言 为了提高效率,进行更为底层的操作,RTOS常采用汇编语句,因此了解常用的汇编语句,很有必要 汇编指令 1..equ:类似于c中的#define,表声明常量 例如:.equ PSW 0x10000 ...

  2. Qt设置程序图标

    修改.pro文件添加一下代码:要求.pro文件和.ico文件在同一文件夹下 RC_ICONS = xxx.ico (你的程序图标)最后重新构建一次即可

  3. nodejs,阿里云手机号一键登录

    const Core = require('@alicloud/pop-core'); const accessKeyId = "xxxx" const accessSecret ...

  4. 4-20mA换算为实际值公式

    Ov = [(Osh - Osl) * (Iv - Isl) / (Ish - Isl)] + Osl 实际工程量 = [((实际工程量)的高限 - (实际工程量)的低限)*(lv - 4) / (2 ...

  5. JAVA的作用

    JAVA的用途广泛:1 .银行系统,政企信息系统,支付系统,大数据平台,网站平台. 2 .Saas云,手机app,云管理系统后台,电商系统后台,桌面工具. JAVA和PYTHON的抉择:JAVA是C语 ...

  6. VP做弹出窗体:查询数据并回传

    1.父页面VP定义传递数据:VP属性:DataContractMembrs 传递参数1:销售订单,用于给到子页面 传递参数2:表格行,用户子页面回传回来父页面(定义为None,通过代码来写进父页面表格 ...

  7. python 的钩子函数

    一.什么是钩子函数 hook函数就是在一定条件下才会执行的函数,将自己实现的函数挂载到挂载点上 1. hook函数:就是我们自己实现的函数,函数类型与挂载点匹配(返回值,参数列表)2. 挂接:也就是h ...

  8. Kotlin源码分析 - 元编程(使用自身语言编写生成自身代码)

    Kotlin源码分析 Kotlin模块FIR分析发现,在生成fir tree的时候,kotlin使用了元编程的技术,以前看到这个技术还是在JastAdd上,使用jastadd语法去写代码,生成Java ...

  9. Centos 7 安装RabbitMq 3.10.7

    1:准备工作 rabbitmq官网查看erlang和rabbitmq的版本关联关系,这里选择 erlang版本:otp_src_25.0  rabbitmqserver版本:3.10.7 官网下载对应 ...

  10. 解决在高分屏电脑上的vmware,linux系统的显示比例不正确的问题

    除了在虚拟机系统内改变显示比例为200%的方法,还有另一种方法: 编辑虚拟机设置--硬件--显示器--指定监视器设置,选择任意监视器的最大分辨率为1920x1080(或者比例保持不变的其他分辨率,例如 ...