1 条题解
-
0
自动搬运
来自洛谷,原作者为

sunnuozhou
**搬运于
2025-08-24 22:11:16,当前版本为作者最后更新于2020-04-23 07:27:00,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本题由BM算法和矩阵特征多项式两部分构成
Berlekamp-Massey算法
Berlekamp-Massey算法,简称BM算法,是用来求解一个数列最短线性递推式的算法,时间复杂度为 。
算法流程
记数列为 ,只考虑 的最短线性递推为 , 和用 推算出的下一个数的差为 。特别的,。 现在考虑如果我们已经知道了 ,如何求 ?
-
如果 ,那么显然
-
如果 为 ,那么 ,共 个0。
-
否则我们需要对 进行调整来得到 。一个简单的思想是找到一个线性递推式 满足 对所有 成立,并且在 处的值为 。那么 就可以等于 。
-
一种可行的构造方案是对于 ,可以使 $R'=\{0,0,..,0,\frac{delta_{i-1}}{delta_w},-\frac{delta_{i-1}}{delta_w}\times R_w\}$,其中0的个数为 。
-
为了使 最短,找到一个 使得 最短即可。
其中有用的 只有当前的 和使 最短的 ,并不需要记录所有 ,空间是 的。 用这个方法生成的线性递推正确性是显然的,但我并不会证明一定是最短的。
但是过了模板题代码
void BM(ll *a,int n,vector<ll>&ans){ ans.clear(); vector<ll> lst; int w=0;ll delta=0; for(int i=1;i<=n;i++){ ll tmp=0; for(int j=0;j<ans.size();j++) tmp=(tmp+a[i-1-j]*ans[j])%mod; if((a[i]-tmp)%mod==0) continue; if(!w){ w=i;delta=a[i]-tmp; for(int j=i;j;j--) ans.push_back(0); continue; } vector<ll> now=ans; ll mul=(a[i]-tmp)*fp(delta,mod-2)%mod; if(ans.size()<lst.size()+i-w) ans.resize(lst.size()+i-w); ans[i-w-1]=(ans[i-w-1]+mul)%mod; for(int j=0;j<lst.size();j++) ans[i-w+j]=(ans[i-w+j]-mul*lst[j])%mod; if(now.size()-i<lst.size()-w){ lst=now;w=i;delta=a[i]-tmp; } } }特征多项式
基本概念
因为模板题要用,就顺带讲一下。
一个 矩阵A的特征多项式为,其中 为 阶单位矩阵, 为行列式运算。 而一个线性递推矩阵如下:
$$A= \left\{ \begin{matrix} a_1 & a_2 & \cdots & a_{n-1} &a_n\\ 1 & 0 & \cdots & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots& \vdots \\ 0 & 0 & \cdots & 0 & 0 \\ 0 & 0 & \cdots & 1 & 0 \\ \end{matrix} \right\} $$$$f(\lambda)= \left | \begin{matrix} \lambda-a_1 & -a_2 & \cdots & -a_{n-1} &-a_n\\ -1 & \lambda & \cdots & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots& \vdots \\ 0 & 0 & \cdots & \lambda & 0 \\ 0 & 0 & \cdots & -1 & \lambda \\ \end{matrix} \right| $$展开第一行得:
$$f(\lambda)=(\lambda-a_1)A_{1,1}+(-a_2)A_{1,2}+\cdots+(-a_n)A_{1,n} $$其中 为 的代数余子式,显然结果为
实用
现在考虑求递推式的第 项,即 的最后一项。 根据Cayley-Hamilton定理可得,
于是有
其中 的最高项次数小于 。 由于 ,可以得到 。 这里可以暴力地快速幂算出 ,也可以使用多项式取模+快速幂的方式
但我不会现在要求的就是 的最后一项。 其中 的最后一项为 。 所以
时间复杂度为 或
代码
ll calc(int m,vector<ll>&coef,ll*h){ if(m<=coef.size()) return h[m]; int k=coef.size(); static ll f[N],g[N],res[N],p[N]; p[0]=-1; for(int i=1;i<=k;i++) p[i]=coef[i-1]; for(int i=0;i<=2*k;i++) f[i]=g[i]=0; f[0]=1; if(k>1) g[1]=1; else g[0]=p[0]; auto mul = [&](ll *a,ll *b,ll *c){ for(int i=0;i<=2*k;i++) res[i]=0; for(int i=0;i<k;i++) for(int j=0;j<k;j++) res[i+j]=(res[i+j]+a[i]*b[j])%mod; for(int i=2*k;i>=k;i--) if(res[i]%mod) for(int j=k;~j;j--) res[i-j]=(res[i-j]+res[i]*p[j])%mod; for(int i=0;i<2*k;i++) c[i]=res[i]; return 0; }; for(;m;m>>=1,mul(g,g,g)) if(m&1) mul(f,g,f); ll ans=0; for(int i=0;i<k;i++) ans=(ans+h[i+1]*f[i])%mod; return ans; }完整代码
#include<bits/stdc++.h> #define ll long long #define lld long ll using namespace std; template<typename tn> void read(tn &a){ tn x=0,f=1; char c=' '; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; a=x*f; } const int N = 10010,mod = 998244353; ll h[N]; int n,m; ll fp(ll a,ll k){ ll ans=1; for(;k;k>>=1,a=a*a%mod) if(k&1) ans=a*ans%mod; return ans; } void BM(ll *a,int n,vector<ll>&ans){ ans.clear(); vector<ll> lst; int w=0;ll delta=0; for(int i=1;i<=n;i++){ ll tmp=0; for(int j=0;j<ans.size();j++) tmp=(tmp+a[i-1-j]*ans[j])%mod; if((a[i]-tmp)%mod==0) continue; if(!w){ w=i;delta=a[i]-tmp; for(int j=i;j;j--) ans.push_back(0); continue; } vector<ll> now=ans; ll mul=(a[i]-tmp)*fp(delta,mod-2)%mod; if(ans.size()<lst.size()+i-w) ans.resize(lst.size()+i-w); ans[i-w-1]=(ans[i-w-1]+mul)%mod; for(int j=0;j<lst.size();j++) ans[i-w+j]=(ans[i-w+j]-mul*lst[j])%mod; if(now.size()-i<lst.size()-w){ lst=now;w=i;delta=a[i]-tmp; } } } ll calc(int m,vector<ll>&coef,ll*h){ if(m<=coef.size()) return h[m]; int k=coef.size(); static ll f[N],g[N],res[N],p[N]; p[0]=-1; for(int i=1;i<=k;i++) p[i]=coef[i-1]; for(int i=0;i<=2*k;i++) f[i]=g[i]=0; f[0]=1; if(k>1) g[1]=1; else g[0]=p[0]; auto mul = [&](ll *a,ll *b,ll *c){ for(int i=0;i<=2*k;i++) res[i]=0; for(int i=0;i<k;i++) for(int j=0;j<k;j++) res[i+j]=(res[i+j]+a[i]*b[j])%mod; for(int i=2*k;i>=k;i--) if(res[i]%mod) for(int j=k;~j;j--) res[i-j]=(res[i-j]+res[i]*p[j])%mod; for(int i=0;i<2*k;i++) c[i]=res[i]; return 0; }; for(;m;m>>=1,mul(g,g,g)) if(m&1) mul(f,g,f); ll ans=0; for(int i=0;i<k;i++) ans=(ans+h[i+1]*f[i])%mod; return ans; } int main(){ read(n);read(m); for(int i=1;i<=n;i++) read(h[i]); vector<ll> ans; BM(h,n,ans); for(auto x:ans) cout<<(x+mod)%mod<<' '; cout<<'\n'; cout<<(calc(m,ans,h)+mod)%mod<<'\n'; return 0; } -
- 1
信息
- ID
- 4484
- 时间
- 4000ms
- 内存
- 500MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者