前言

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

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

最后仔细想想思路那么的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. 学JAVA第十七天,接口与抽象方法

    JAVA接口可以让代码更加有合理的规范性,就想一个项目小组,组长要负责把成员的代码整合,但是每个成员写的方式都是按照他们自己的想法来写的, 所以,整合起来就非常麻烦. 但是,如果我们的组长制作了一个接 ...

  2. Java开发笔记(八十四)文件与目录的管理

    程序除了处理内存中的数据结构,还要操作磁盘上的各类文件,这里的磁盘是个统称,泛指可以持久保留数据的存储介质,包括但不限于:插在软驱中的软盘.固定在机箱中的硬盘.插在光驱中的光盘.插在USB接口上的U盘 ...

  3. js中关于两个变量的比较

    今天在匆忙的写代码过程中,测试突然跑过来跟我说,有一个小的bug,但是不能完全的复现,但确实存在.需要我们这边参与查找.首先来说一下我们这个的业务逻辑,其实非常的简单,就是一个开房间的后台,里面有一项 ...

  4. js中console使用1

    js中console主要用于debug时使用 测试代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN ...

  5. JavaScript实现获取两个排序数组的中位数算法示例

    本文实例讲述了JavaScript排序代码实现获取两个排序数组的中位数算法.分享给大家供大家参考,具体如下: 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个 ...

  6. Spring注入对象(3)

    2019-03-08/10:45:04 演示:对Product对象,注入一个Category对象 1.创建pojo类 Product类中有对Category对象的setter getter packa ...

  7. html 表单input录入内容校验

    <p>文本框只能输入数字代码(小数点也不能输入)</p><input onkeyup="this.value=this.value.replace(/\D/g, ...

  8. Android Studio教程05-Parcelables和Bundles.md

    Parcelable并且Bundle对象旨在用于跨IPC / Binder事务等进程边界,活动与意图之间以及跨配置更改存储瞬态.本页面提供使用Parcelable和Bundle对象的建议和最佳实践 . ...

  9. Linux下使用yum安装软件命令

    1.yum list | grep 要下载的文件名字2.yum install 完整文件名字3.rpm -qa | grep 软件名字 //查看版本

  10. 深入浅出KNN算法(一) KNN算法原理

    一.KNN算法概述 KNN可以说是最简单的分类算法之一,同时,它也是最常用的分类算法之一,注意KNN算法是有监督学习中的分类算法,它看起来和另一个机器学习算法Kmeans有点像(Kmeans是无监督学 ...