前言

嗯   我之前的不知道多少天看这个的时候到底在干什么呢

为什么那么。。  可能大佬们太强的缘故

最后仔细想想思路那么的emmm

不说了  要落泪了

唔唔唔


前置

多项式求逆

多项式除法/取模


常系数齐次递推目的

求一个满足k阶齐次线性递推数列ai的第n项

即: 

给出f1--fk,a0--ak-1求an

N=1e9,K=32000


常系数齐次递推主要思路

emmm矩阵快速幂怎么样都应该会的

设转移矩阵为A,st=[a0,a1...ak-2,ak-1]为初始矩阵

显然an=(st*An)0

O(k3logn)和O(k2logklogn)的矩阵快速幂在此范围下显然太暴力了

发现k过大时时间复杂度主要花在矩阵乘法上

考虑如何不用矩阵通过多项式来计算答案

先考虑把An转化为A0--Ak-1组合出来的和

设An=Q(A)*G(A)+R(A)

Q,G,R是以矩阵为x(参数)的多项式

当强制G的多项式的最高次数为k次方

那么可写成An=Q(A)*G(A)+ciAi

此时如果再强制试使得G(A)为0时

那么Q(A)*G(A)=0

An=ciAi=R(A)

所以ciAi=An%G(A)

通过多项式取模就可将An转化为ciAi

通过上面的推导发现an=(st*An)0=(st*ciAi)0=(ciAist)0

因为我们每次只取矩阵的第0项  每转移一次下一项就往上移一个位置 原来的第0项就去掉

所以Aist就等于sti

最后的an=cisti

这样只要找出之前要求的那个G(A)就可以O(k)得出答案了

那么如何求出G(A)

设G(A)=giAi=0

这里有个我暂时不会的结论

如果递推系数为f1--fn

那么gk-i=fi,gk=1

所以最后流程就是

1.求出G(A)

2.用快速幂和多项式取模求出An在模G(A)时的余数R(A) 也就是把An转化为A1--Ak的组合

3.计算答案an=cisti


代码

这 时隔多年我中于调出来了一份常数巨大的代码

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define C getchar()-48
inline ll read()
{
ll s=,r=;
char c=C;
for(;c<||c>;c=C) if(c==-) r=-;
for(;c>=&&c<=;c=C) s=(s<<)+(s<<)+c;
return s*r;
}
const int p=,G=,N=;
int n,k,mx,cs,qvq,tz;
ll rev[N];
ll f[N],st[N],g[N],invg[N];
ll tmp[N],tmp1[N],tmp2[N],tmpa[N],tmpb[N];
ll a[N],ans[N];
inline ll ksm(ll a,ll b)
{
ll ans=;
while(b)
{
if(b&) ans=(ans*a)%p;
a=(a*a)%p;
b>>=;
}
return ans;
}
inline void ntt(ll *a,ll n,ll kd)
{
for(int i=;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int i=;i<n;i<<=)
{
ll gn=ksm(G,(p-)/(i<<));
for(int j=;j<n;j+=(i<<))
{
ll t1,t2,g=;
for(int k=;k<i;k++,g=g*gn%p)
{
t1=a[j+k],t2=g*a[j+k+i]%p;
a[j+k]=(t1+t2)%p,a[j+k+i]=(t1-t2+p)%p;
}
}
}
if(kd==) return;
ll ny=ksm(n,p-);
reverse(a+,a+n);
for(int i=;i<n;i++) a[i]=a[i]*ny%p;
}
inline void cl(ll *a,ll *b,ll n,ll m,ll len,ll w)
{
for(int i=;i<len;i++) tmp1[i]=i<n?a[i]:;
for(int i=;i<len;i++) tmp2[i]=i<m?b[i]:;
for(int i=;i<len;i++) rev[i]=(rev[i>>]>>)|((i&)<<(w-));
}
inline void polyinv(ll *a,ll *b,ll ed)
{
b[]=ksm(a[],p-);
for(int k=,j=;k<=(ed<<);k<<=,j++)
{
ll len=k<<;
cl(a,b,k,k,len,j+);
ntt(tmp1,len,);ntt(tmp2,len,);
for(int i=;i<len;i++) b[i]=tmp2[i]*(2ll-tmp1[i]*tmp2[i]%p+p)%p;
ntt(b,len,-);
for(int i=k;i<len;i++) b[i]=;
}
}
inline void polymul(ll *a,ll *b,ll *c,ll n,ll m)
{
ll len=,w=;
while(len<=(n+m)) len<<=,w++;
cl(a,b,n,m,len,w);
ntt(tmp1,len,);ntt(tmp2,len,);
for(int i=;i<len;i++) c[i]=tmp1[i]*tmp2[i]%p;
ntt(c,len,-);
}
inline void polymod(ll *a,ll n=mx<<,ll m=k)
{
int ed=(mx<<);while(a[--ed]==);if(ed<k) return; n=ed;
reverse(a,a++n);
polymul(a,invg,tmpa,n+,n-m+);
reverse(tmpa,tmpa+n-m+);
reverse(a,a++n); polymul(g,tmpa,tmpb,m+,n-m+);
for(int i=;i<k;i++) a[i]=(a[i]-tmpb[i]+p)%p;
for(int i=k;i<=ed;i++)a[i]=;
for(int i=;i<(mx<<);i++) tmpa[i]=tmpb[i]=;
}
int main()
{
n=read(),k=read();mx=,cs=;
while(mx<=k) mx<<=,cs++;
for(int i=;i<=k;i++) f[i]=read(),f[i]=f[i]<?f[i]+p:f[i];
for(int i=;i<k;i++) st[i]=read(),st[i]=st[i]<?st[i]+p:st[i];
for(int i=;i<=k;i++) g[k-i]=p-f[i];g[k]=;
for(int i=;i<=k;i++) tmp[i]=g[i]; reverse(tmp,tmp++k);
polyinv(tmp,invg,mx);
for(int i=mx;i<=(mx<<);i++) invg[i]=;
for(int i=;i<=k;i++) tmp[i]=;
for(int i=;i<(mx<<);i++) rev[i]=(rev[i>>]>>)|((i&)<<(cs+-));
ans[]=;a[]=;
while(n)
{
if(n&){polymul(ans,a,ans,k,k); polymod(ans);}
polymul(a,a,a,k,k); polymod(a);
n>>=;
}
for(int i=;i<k;i++) qvq=(qvq+ans[i]*st[i])%p;
cout<<qvq;
return ;
}

Re.常系数齐次递推的更多相关文章

  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. 【BZOJ4944】[NOI2017]泳池(线性常系数齐次递推,动态规划)

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

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

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

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

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

  8. LOJ 2304 「NOI2017」泳池——思路+DP+常系数线性齐次递推

    题目:https://loj.ac/problem/2304 看了各种题解…… \( dp[i][j] \) 表示有 i 列.第 j 行及以下默认合法,第 j+1 行至少有一个非法格子的概率,满足最大 ...

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

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

随机推荐

  1. C#根据屏幕分辨率改变图片尺寸

    最近工作中遇到一个问题,就是需要将程序文件夹中的图片根据此时电脑屏幕的分辨率来重新改变图片尺寸 以下为代码实现过程: 1.获取文件夹中的图片,此文件夹名为exe程序同目录下 //读取文件夹中文件 Di ...

  2. jQuery(一)、核心

    我认为,学习一门语言,主要是掌握它的思想与用途,就好比谈恋爱一样,你只要猜测到了对方的想法,就能够知情达意.废话不多说,我们开始今天学习的进度,加油ヾ(◍°∇°◍)ノ゙ 1. jQuery([sele ...

  3. element-tree-grid(表格树)的使用

    表格树,element-tree-grid需要单独下载并再配合elementUi里el-table使用. 步骤:1.npm install element-tree-grid --save(下载ele ...

  4. Oracle字符到数值转换错误

    [错误] [问题分析] line 3: 定义 NUM_VAL varchar2(500); line 9: NUM_VAL := 'NUM'+1; NUM_VAL是一个varchar类型的数据,而在数 ...

  5. ElasticSearch head 插件安装

    head 客户端可以很方便在上面创建索引,类型,文档,还有查询,使用它管理elasticsearch 提高效率. 在安装head 客户端之前必须安装node.js 环境,因为它是用node.js 编写 ...

  6. Linux常用命令--文件操作

    常用Linux命令笔记(1) 1. 创建文件/文件夹 参考博客:https://www.cnblogs.com/lclq/p/5741852.html. 使用cat命令创建新文件: 输入命令 # ca ...

  7. vue和angular的区别:

    相同: 1.数据绑定:vue和angular绑定都可以用{{}} 2.都支持内置指令和自定义指令 3.都支持内置过滤器和自定义过滤器. 区别: 1.学习成本和API 设计:vue相比于angular来 ...

  8. servlet之转发与重定向的区别

    转发(服务器端跳转):  一次请求 <jsp:forward> request.getRequestDispatcher("new.jsp").forward(requ ...

  9. 【转】网页禁止后退键BackSpace的JavaScript实现(兼容IE、Chrome、Firefox、Opera)

    var forbidBackSpace = function (e) { // 获取event对象 var ev = e || window.event; // 获取事件源 var obj = ev. ...

  10. Dell服务器U盘安装Windows Server时识别不到硬盘

    Dell服务器U盘安装Windows Server时识别不到硬盘 1.下载驱动http://downloads.dell.com/FOLDER03688531M/1/SAS-RAID_Driver_T ...