常系数齐次线性递推 & 拉格朗日插值
常系数齐次线性递推
具体记在笔记本上了,以后可能补照片,这里稍微写一下,主要贴代码。
概述
形式:
\]
矩阵乘法是\(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 ...
随机推荐
- HDU 2079 dp解法
选课时间(题目已修改,注意读题) Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu_2444The Accomodation of Students(二分图的判定和计算)
hdu_2444The Accomodation of Students(二分图的判定和计算) 标签:二分图匹配 题目链接 题意: 问学生是否能分成两部分,每一部分的人都不相认识,如果能分成的话,两两 ...
- vue -- v-cloak解决刷新或者加载出现闪烁(显示变量)
在使用vue绑定数据的时候,渲染页面时会出现变量闪烁,例如 <div class="#app"> <p>{{value.name}}</p> & ...
- Linux 用户组及用户管理
查看所有组的信息:(信息保存在/etc/group文件中) 其中每段信息用:分割 ,每段的含义如下: 用户名组名:密码:用户组的id:用户组所包含的用户(多个用户用,分割) 查看所有的用户信息:(信息 ...
- 用于浏览器桌面通知的Web API 接口 -notification
notification 接口用于浏览器向用户提供通知内容:常见的如网页版的微信: 1.实现,需要Notifications API 提供的通知接口: 用法: let notification = n ...
- 【自制工具类】struts返回json数据包装格式类
自己写的一个给struts返回的json数据包装格式类,不喜勿喷,原创,需在项目中引入com.alibaba.fastjson的jar包 先看下效果(这里没有使用msg,有兴趣的往下看): 上demo ...
- 【分享】一个集成tracert和ping的网络监测工具
最近接到一个需求,需求背景是这样的:目前Windows平台下本身都有tracert和ping的实现,而且可以直接在cmd下使用. 需求中有两个要求: 1. Windows平台中的tracert执行速度 ...
- 关于将dede织梦data目录迁移出web目录
关于将dede织梦data目录迁移出web目录织梦官方提供了一个教程,但是如果你是按照他们提供的教程做的话会出现很多问题.比如验证码问题,图片显示问题等等一大堆.织梦官方这种是很不负责任的,因为那个教 ...
- 解决DEDECMS Call to undefined function dede_htmlspecialchars()
作者:DEDECMS建站网 关注: 3610 时间:2015-11-18 16:39 内容详情 以下内容您可能感兴趣: 织梦官方在2015年6月18日更新了织梦5.7,为了兼容php5.4+,修改了/ ...
- 云主机与vps虚拟主机的区别
云计算时代,云主机其可扩展性.价格便宜.安全可靠的特性深受企业和开发者欢迎,但目前有些IDC企业,新瓶装旧酒,将虚拟主机.VPS进行包装推出所谓的云主机服务,为了帮助用户更好的辨别和挑选云主机,下文详 ...