常系数齐次线性递推 & 拉格朗日插值
常系数齐次线性递推
具体记在笔记本上了,以后可能补照片,这里稍微写一下,主要贴代码。
概述
形式:
\]
矩阵乘法是\(O(k^3 \log n)\)
利用特征多项式可以做到\(O(k^2\log n)\)
特征多项式
\]
是关于\(\lambda\)的\(n\)次多项式
根据\(Cayley-hamilton\)定理得到 \(f(M)=0\)(zero matrix),所以就能得到\(M^k\)与\(M^0...M^{k-1}\)的线性递推关系,\(M^n\)也可以用\(M^0...M^{k-1}\)线性表示,多项式乘法快速幂求这个递推关系的系数。最后代入就行了。
其实就是:
\]
所以还需要多项式求余。
这玩意卡我好长时间,然后发现就是手算的原理。当然用毒瘤算法可以做到nlogn
两种形式
对于常系数齐次线性递推关系,我们可以一眼看出它的特征多项式
\]
并且最高次系数为1,求余很简单
对于一般的矩阵,需要求行列式得到n+1个点的值,然后拉格朗日插值,这一步复杂度\(O(n^4)\)
拉格朗日插值公式:
\]
代码
例题为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;
}
常系数齐次线性递推 & 拉格朗日插值的更多相关文章
- 【Luogu4723】线性递推(常系数齐次线性递推)
[Luogu4723]线性递推(常系数齐次线性递推) 题面 洛谷 题解 板子题QwQ,注意多项式除法那里每个多项式的系数,调了一天. #include<iostream> #include ...
- 【BZOJ4161】Shlw loves matrixI (常系数齐次线性递推)
[BZOJ4161]Shlw loves matrixI (常系数齐次线性递推) 题面 BZOJ 题解 \(k\)很小,可以直接暴力多项式乘法和取模. 然后就是常系数齐次线性递推那套理论了,戳这里 # ...
- 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)
这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...
- 【瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)
[背诵瞎讲] Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18) 看CSP看到一题"线性递推式",不会做,去问了问zsy怎么做,他并 ...
- BZOJ4161 常系数齐次线性递推
问了数竞的毛毛搞了一番也没太明白,好在代码蛮好写先记下吧. #include<bits/stdc++.h> using namespace std; ,mod=1e9+; int n,k, ...
- Re.常系数齐次递推
前言 嗯 我之前的不知道多少天看这个的时候到底在干什么呢 为什么那么.. 可能大佬们太强的缘故 最后仔细想想思路那么的emmm 不说了 要落泪了 唔唔唔 前置 多项式求逆 多项式除法/取模 常 ...
- 【BZOJ4944】[NOI2017]泳池(线性常系数齐次递推,动态规划)
[BZOJ4944][NOI2017]泳池(线性常系数齐次递推,动态规划) 首先恰好为\(k\)很不好算,变为至少或者至多计算然后考虑容斥. 如果是至少的话,我们依然很难处理最大面积这个东西.所以考虑 ...
- 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<= ...
- 线性齐次递推式快速求第n项 学习笔记
定义 若数列 \(\{a_i\}\) 满足 \(a_n=\sum_{i=1}^kf_i \times a_{n-i}\) ,则该数列为 k 阶齐次线性递推数列 可以利用多项式的知识做到 \(O(k\l ...
随机推荐
- poj_1144Network(tarjan求割点)
poj_1144Network(tarjan求割点) 标签: tarjan 割点割边模板 题目链接 Network Time Limit: 1000MS Memory Limit: 10000K To ...
- Sql Server——数据增删改
所谓数据的增删改就是在创建好数据库和表后向表中添加数据.删除表中的数据.更改表中的一些数据. 新增数据: 语法一: insert into 表名 values (数据内容) --这里需要 ...
- phpstorm ctrl+shift+F键不管用,不弹出搜索弹框
般热键冲突搜狗默认简繁切换组合键位ctrl+shift+F故outlook2011按三建且失效应该能看搜狗输入状态简繁变搜狗设置按键-取消选简繁切换热键即在任务栏的语言地方点击一下再点击语言首选项.进 ...
- thinkphp操作完提示信息该怎么弄成弹出层啊?
http://www.thinkphp.cn/topic/21929.html 浏览:11879 发布日期:2014/08/22 分类:求助交流 关键字: thinkphp success跳转 弹出层 ...
- 用程序读取CSV文件的方法
CSV全称 Comma Separated values,是一种用来存储数据的纯文本文件格式,通常用于电子表格或数据库软件.用Excel或者Numbers都可以导出CSV格式的数据. CSV文件的规则 ...
- 【笔记】BFC 模型知识整理
网上看了很多 BFC 的概念,发现都说得不是很完整和深入,刚好最近看了一些视频教程说到了 BFC 概念所以记录一下. BFC 的概念: BFC 全称:Block format context 块级格式 ...
- input===》name属性异常错误
<input type="text" name="status" /> 使用springMVC时,如果有这个输入框,此框必须要填,且必须是数字,否者 ...
- 注入理解之APC注入
近期学习做了一个各种注入的MFC程序,把一些心得和体会每天分享一些 APC(Asynchronous procedure call)异步程序调用,在NT中,有两种类型的APCs:用户模式和内核模式.用 ...
- RocketMQ环境搭建(双master模式)
介绍: 多Master模式,一个集群无Slave,全是Master,例如2个Master或者3个Master. 优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时, ...
- node.js进阶话题
< h3>notes_控制流 //forloopi.js var fs = require('fs'); var files = ['a.txt', 'b.txt', 'c.txt']; ...