常系数齐次线性递推

具体记在笔记本上了,以后可能补照片,这里稍微写一下,主要贴代码。


概述

形式:

\[h_n = a_1 h_{n-1}+a_2h_{n-2}+...+a_kh_{n-k}
\]

矩阵乘法是\(O(k^3 \log n)\)

利用特征多项式可以做到\(O(k^2\log n)\)

特征多项式

特征值和特征向量

特征多项式

\[f(\lambda) = \mid M - \lambda I\mid
\]

关于\(\lambda\)的\(n\)次多项式

根据\(Cayley-hamilton\)定理得到 \(f(M)=0\)(zero matrix),所以就能得到\(M^k\)与\(M^0...M^{k-1}\)的线性递推关系,\(M^n\)也可以用\(M^0...M^{k-1}\)线性表示,多项式乘法快速幂求这个递推关系的系数。最后代入就行了。

其实就是:

\[M^n = M^n \mod f(M)
\]

所以还需要多项式求余

这玩意卡我好长时间,然后发现就是手算的原理。当然用毒瘤算法可以做到nlogn

两种形式

对于常系数齐次线性递推关系,我们可以一眼看出它的特征多项式

\[f(\lambda) = \lambda^k - a_1 \lambda^{k-1} -...-a_k
\]

并且最高次系数为1,求余很简单


对于一般的矩阵,需要求行列式得到n+1个点的值,然后拉格朗日插值,这一步复杂度\(O(n^4)\)

拉格朗日插值公式:

\[\sum_{j=0}^n y_j \prod_{i=0 , i\neq j}^n \frac{x-x_i}{x_j - x_i}
\]



代码

例题为bzoj 4161 & bzoj 4162

常系数齐次线性递推

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 4005, mo = 1e9+7;
inline int read(){
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
} int n, k, a[N], f[N], b[N], c[N], ans;
void mul_mod(int *x, int *y) {
static int c[N];
for(int i=0; i<k<<1; i++) c[i] = 0;
for(int i=0; i<k; i++)
for(int j=0; j<k; j++) c[i+j] = (c[i+j] + (ll) x[i] * y[j]) %mo;
// mod f(M)
for(int i=2*k-2; i>=k; i--)
for(int j=1; j<=k; j++) c[i-j] = (c[i-j] + (ll) c[i] * a[j]) %mo;
for(int i=0; i<k; i++) x[i] = c[i];
} void Pow(int *a, int b, int *ans) {
for(; b; b>>=1, mul_mod(a, a)) if(b&1) mul_mod(ans, a);
}
int main() {
freopen("in", "r", stdin);
n=read(); k=read();
for(int i=1; i<=k; i++) a[i] = read(), a[i] += a[i] < 0 ? mo : 0;
for(int i=0; i<k; i++) f[i] = read(), f[i] += f[i] < 0 ? mo : 0;
c[1] = 1; b[0] = 1;
Pow(c, n, b);
for(int i=0; i<k; i++) ans = (ans + (ll) b[i] * f[i]) %mo;
printf("%d\n", ans);
}

一般矩阵快速幂

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define pll pair<ll, ll>
#define fir first
#define sec second
const int N = 52, mo = 1e9+7;
inline int read(){
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
} ll Pow(ll a, int b) {
ll ans = 1;
for(; b; b>>=1, a=a*a%mo)
if(b&1) ans=ans*a%mo;
return ans;
} int n, k, a[N][N], t[N][N], t2[N][N], ans[N][N];
char s[10005]; void mul(int a[N][N], int b[N][N], int c[N][N]) {
for(int i=1; i<=n; i++)
for(int k=1; k<=n; k++) if(a[i][k])
for(int j=1; j<=n; j++) if(b[k][j])
c[i][j] = (c[i][j] + (ll) a[i][k] * b[k][j]) %mo;
} int det(int a[N][N]) {
int s = 0;
for(int i=1; i<=n; i++) {
int r;
for(r=i; r<=n; r++) if(a[r][i]) break;
if(r == n+1) return 0;
if(r != i) {
s ^= 1;
for(int j=1; j<=n; j++) swap(a[r][j], a[i][j]);
}
ll inv = Pow(a[i][i], mo-2);
for(int k=i+1; k<=n; k++) {
ll t = (ll) (mo - a[k][i]) * inv %mo;
for(int j=i; j<=n; j++) a[k][j] = (a[k][j] + t * a[i][j]) %mo;
}
}
ll ans = 1;
for(int i=1; i<=n; i++) ans = ans * a[i][i] %mo;
return (s&1) ? mo - ans : ans;
} struct poly {
int a[N<<1];
poly(int x=0) {memset(a, 0, sizeof(a)); a[0] = x;}
int& operator [](int x) {return a[x];} poly operator + (poly b) {
poly c;
for(int i=0; i<=n; i++) c[i] = (a[i] + b[i]) %mo;
return c;
}
poly operator * (ll b) {
poly c;
for(int i=0; i<=n; i++) c[i] = (ll) a[i] * b %mo;
return c;
}
poly operator * (poly b) {
poly c;
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++) c[i+j] = (c[i+j] + (ll) a[i] * b[j]) %mo;
return c;
}
poly operator * (pll t) {
ll k = t.fir, b = t.sec;
poly c(a[0] * b %mo);
for(int i=1; i<=n; i++) c[i] = (a[i-1] * k + a[i] * b) %mo;
return c;
}
friend poly operator % (poly a, poly b) {
for(int i=n; i>=0; i--) {
ll t = (ll) (mo - a[i+n]) * Pow(b[n], mo-2) %mo;
for(int j=0; j<=n; j++) a[i+j] = (a[i+j] + b[j] * t) %mo;
}
return a;
}
} ; int y[N];
int main() {
freopen("in", "r", stdin);
scanf("%s",s);
n=read();
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) a[i][j] = read();
for(int x=0; x<=n; x++) {
memcpy(t, a, sizeof(a));
for(int i=1; i<=n; i++) t[i][i] = (t[i][i] + mo - x) %mo;
y[x] = det(t);
}
poly f;
for(int j=0; j<=n; j++) {
poly t(1);
for(int i=0; i<=n; i++) if(i != j)
t = (t * make_pair(1, mo-i) ) * Pow(j-i+mo, mo-2);
t = t * y[j];
f = f + t;
} poly p, b(1); p[1] = 1;
for(int i=strlen(s)-1; i>=0; i--, p = p * p % f)
if(s[i] == '1') b = b * p % f; memset(t, 0, sizeof(t));
for(int i=1; i<=n; i++) t[i][i] = 1;
for(int p=0; p<n; p++) {
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
ans[i][j] = (ans[i][j] + (ll) t[i][j] * b[p]) %mo;
memset(t2, 0, sizeof(t2));
mul(t, a, t2);
memcpy(t, t2, sizeof(t2));
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) printf("%d%c", ans[i][j], " \n"[j==n]);
return 0;
}

常系数齐次线性递推 & 拉格朗日插值的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. Re.常系数齐次递推

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

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

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

  8. 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<= ...

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

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

随机推荐

  1. BZOJ1226: [SDOI2009]学校食堂Dining

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1226 状压dp. f[i][s][k]表示原顺序中前i-1个人都吃了饭,当前状态为s(i及i之 ...

  2. POJ 2387 Til the Cows Come Home(模板——Dijkstra算法)

    题目连接: http://poj.org/problem?id=2387 Description Bessie is out in the field and wants to get back to ...

  3. webzip怎么用 如何用webzip下载整个网站?

    相信很多站长对webzip这款软件都并不感到陌生,它功能强大,能够完整下载网站的内容,或者你也可以选择自行设置下载的层数.文件类型.网页与媒体文件的定位等等.具体详情你可以在百度上去搜一下.由于web ...

  4. SSL和SSH有什么区别

    SSL 是一种安全协议,它为网络(例如因特网)的通信提供私密性.SSL 使应用程序在通信时不用担心被窃听和篡改. SSL 实际上 是共同工作的两个协议:"SSL 记录协议"(SSL ...

  5. (实用篇)使用PHP生成PDF文档

    http://mp.weixin.qq.com/s?__biz=MzIxMDA0OTcxNA==&mid=2654254929&idx=1&sn=8715d008d19af70 ...

  6. 《并行程序设计导论》——OpenMP

    OpenMP看着很好,实际上坑很多. 如果真的要求性能和利用率,还是专门写代码吧.而且MS的VS里只有2.X的版本.

  7. rsync - 远程同步工具

    一直没有对这个命令太有深入的理解 简介 rsync 即 remote sync,一个远程与本地文件同步工具.rsync 使用的算法能够最小化所需复制的数据,因为它只移动那些修改了的文件. rsync ...

  8. centos7 安装jdk 1.8

    1.下载jdk1.8  for linux的安装包 jdk-8u11-linux-x64.tar.gz,下载地址:http://download.oracle.com/otn-pub/java/jdk ...

  9. 关于flying框架

    开发10多年了,开发过程中遇到的最大的问题: ①项目的代码越来越多了,越来越复杂了,而客户的需求,你还不得不往里面加入新代码. ②开发了很多项目,每次复用时却只能把代码copy来copy去,然后调试. ...

  10. 一个滑动选中RecyclerView中Item的布局SlidingCheckLayout,手指滑过Item时多项选中。

    SlidingCheckLayout是一个滑动选中RecyclerView中Item的布局,手指滑过Item时多项选中. 作者:竹尘居士 github:https://github.com/homgw ...