常系数齐次线性递推

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


概述

形式:

\[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. HDU1097-A hard puzzle-快速幂+取模

    快速幂: 代码: kuaisumi(ll a,ll b){      ll ans=;      while(b){          ==){              ans=ans*a;     ...

  2. HDU_5523Game

    Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Sub ...

  3. GO开发[四]:golang函数

    函数 1.声明语法:func 函数名 (参数列表) [(返回值列表)] {} 2.golang函数特点: a. 不支持重载,一个包不能有两个名字一样的函数 b. 函数是一等公民,函数也是一种类型,一个 ...

  4. 【Sql】mySQL在windows环境启动

    SQL的不同版本在Windows环境启动配置方法不同,此处仅介绍 5.7.20的配置方法: 1.登录mysql官网下载windows环境下的工具压缩包 http://dev.mysql.com/dow ...

  5. [高并发]抢红包设计(使用redis)

    假设一个需求,在某个预告活动中准备了10w个红包,100w人在某个时间点去开抢,每人只能抢1次,如何保证性能和准确性,下面我给出我的一个设计方案,抛砖引玉 分析瓶颈 查询用户是否已参与过活动 获取一个 ...

  6. javascript 之原型、原型链-14

    原型 原型是一个对象,每个函数对象(在javascript 之对象中说过函数也是对象 )都有一个属性(prototype)指向这个对象--原型对象,这个对象的作用是让所有对象实例共享原型对象中的属性. ...

  7. IntelliJ IDEA 配置 smartGit

    教你如何在IntelliJ IDEA中配置smartGit? 一.第一种方式: 1.在启动IDEA工具时,点击下拉按钮"Check out from Version Control" ...

  8. 使用pscp命令在Windows与linux之间拷贝文件

    在Linux环境下做开发时,我们可能会在windows下远程控制Linux系统,本文介绍如何使用putty的pscp.exe在Windows和 Linux(本文使用fedora)之间copy文件. 工 ...

  9. 怎么从一台电脑的浏览器输入地址访问另一台电脑服务器(WAMP服务器已搭建,PHPSTORM装好了)

    服务器电脑WAMP环境搭建好了,浏览器输入LOCALHOST就能访问本地 WAMP/WWW 目录下PHP文件,怎么样才能从另一台电脑通过浏览器访问呢?求详细步骤... glwbdtb | 浏览 180 ...

  10. php对数组进行分页

      3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ...