感性理解Berlekamp-Massey算法
引入
BM算法主要解決的是根據(jù)數(shù)列求最短線性齊次遞推式的問題在OI中主要輔助打表使用
即:已知FFF,求序列AAA使得
Fn=∑i=1mAiFn?i(n>m)F_n=\sum_{i=1}^mA_iF_{n-i} \quad(n>m)Fn?=i=1∑m?Ai?Fn?i?(n>m)
其中mmm盡量小
算法流程
文中的所有序列下標均從111開始,并且為了方便規(guī)定000和負下標值均為000
該算法采用增量法,即我們求前nnn項的遞推式,假設已經(jīng)求出了前n?1n-1n?1項的遞推式,我們記為AAA,考慮計算加上第nnn項后的遞推式A′A'A′
設AAA的長度為mmm,也就是
m<k<n,Fk=∑i=1mAiFk?im<k<n,F_k=\sum_{i=1}^mA_iF_{k-i}m<k<n,Fk?=i=1∑m?Ai?Fk?i?
我們用現(xiàn)在不知道對不對的遞推式,也就是上一個遞推式AAA,算出FnF_nFn?不知道對不對的值,記為Fn′F'_nFn′?,也就是
Fn′=∑i=1mAiFn?iF'_n=\sum_{i=1}^mA_iF_{n-i}Fn′?=i=1∑m?Ai?Fn?i?
如果Fn=Fn′F_n=F'_nFn?=Fn′?,那么這個遞推式暫時沒有問題,繼續(xù)往后,即A′=AA'=AA′=A
否則我們把這一位差了多少算出來,即
Δn=Fn?Fn′\Delta_n=F_n-F'_nΔn?=Fn??Fn′?
注意有可能是負數(shù)
現(xiàn)在我們需要修正當前的遞推式AAA
仔細觀察這個遞推式
k<n,∑i=1mAiFk?i=Fk∑i=1mAiFn?i=Fn?Δnk<n,\sum_{i=1}^mA_iF_{k-i}=F_k\\ \sum_{i=1}^{m}A_iF_{n-i}=F_n-\Delta_nk<n,i=1∑m?Ai?Fk?i?=Fk?i=1∑m?Ai?Fn?i?=Fn??Δn?
和我們希望得到的遞推式,這里設它長度為m′m'm′,顯然有m′≥mm'\geq mm′≥m
k<n,∑i=1m′Ai′Fk?i=Fk∑i=1m′Ai′Fn?i=Fnk<n,\sum_{i=1}^{m'}A'_iF_{k-i}=F_k\\ \sum_{i=1}^{m'}A'_iF_{n-i}=F_nk<n,i=1∑m′?Ai′?Fk?i?=Fk?i=1∑m′?Ai′?Fn?i?=Fn?
我們可以考慮給AAA加上一個遞推式DDD得到A′A'A′,容易知道它滿足
k<n,∑i=1m′DiFk?i=0∑i=1m′DiFn?i=Δnk<n,\sum_{i=1}^{m'}D_iF_{k-i}=0\\ \sum_{i=1}^{m'}D_iF_{n-i}=\Delta_nk<n,i=1∑m′?Di?Fk?i?=0i=1∑m′?Di?Fn?i?=Δn?
現(xiàn)在嘗試構(gòu)造一個DDD
我們找到之前的一個匹配失敗的遞推式RRR,設它失敗的位置為ppp,當時這個位置的差為Δp\Delta_pΔp?。為了避免標識太多看暈,我們還是把RRR的長度設為mmm,之后的mmm都是指RRR的長度
即
k<p,∑i=1mRiFk?i=Fk∑i=1mRiFp?i=Fk?Δpk<p,\sum_{i=1}^mR_iF_{k-i}=F_k\\ \sum_{i=1}^mR_iF_{p-i}=F_k-\Delta_pk<p,i=1∑m?Ri?Fk?i?=Fk?i=1∑m?Ri?Fp?i?=Fk??Δp?
重新理一下這個式子的含義:
對當前位置k<pk<pk<p,我們從kkk往前面找mmm個數(shù)和RRR卷一下,然后用FkF_kFk?去減,都得到了000
唯獨ppp不同,我們減出來得到了Δp\Delta_pΔp?
發(fā)現(xiàn)這個跟DDD神似
所以我們考慮這么構(gòu)造DDD:
開始先放n?p?1n-p-1n?p?1個000進去,表示卷積的位置向左平移n?p?1n-p-1n?p?1位,實際上開始與D1D_1D1?對應相乘的位置是k?n+pk-n+pk?n+p,之后D2,D3,…,DmD_2,D_3,\dots,D_mD2?,D3?,…,Dm?的對應相乘位置不斷向左挪
這時我們發(fā)現(xiàn)nnn恰好對應到了ppp,也就是RRR中唯一減出來不為000的位置
所以考慮構(gòu)造這個減法 設x=ΔnΔpx={\Delta_n\over\Delta p}x=ΔpΔn??
在n?pn-pn?p的位置放一個xxx
然后把RRR的每一位取?x-x?x倍接在后面
這樣不考慮xxx的話,nnn對應的卷出來是FpF_pFp?減去用RRR算出來的Fp′F'_pFp′?,即Δp\Delta_pΔp?,乘上xxx得到Δn\Delta_nΔn?。其他位置因為Fk=Fk′F_k=F'_kFk?=Fk′?,所以卷出來是000。
也就是
D={0,0,…,0?n-p-1個0,x,?xR1,?xR2,…,?xRn}D=\{ \underbrace{0,0,\dots,0}_\text{n-p-1個0},x,-xR_1,-xR_2,\dots,-xR_n \}D={n-p-1個00,0,…,0??,x,?xR1?,?xR2?,…,?xRn?}
可(bu)以(yong)證明,選取最近的RRR一定是最優(yōu)的
把AAA加上DDD就可以得到A′A'A′
復雜度O(n2)O(n^2)O(n2)
模板題
道理我都懂,為啥好好的BM模板要加個線性遞推
注:此代碼只有BM部分
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #define MAXN 10005 using namespace std; inline int read() {int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } const int MOD=998244353; inline int add(const int& x,const int& y){return x+y>=MOD? x+y-MOD:x+y;} inline int dec(const int& x,const int& y){return x<y? x-y+MOD:x-y;} typedef long long ll; inline int qpow(int a,int p) {int ans=1;while (p){if (p&1) ans=(ll)ans*a%MOD;a=(ll)a*a%MOD;p>>=1;}return ans; } int F[MAXN],R[MAXN]; int las[MAXN],tmp[MAXN],p,delta; int main() {int n,m;n=read(),m=read();for (int i=1;i<=n;i++) F[i]=read();for (int i=1;i<=n;i++){int res=0;for (int j=1;j<=R[0];j++) res=add(res,(ll)R[j]*F[i-j]%MOD);if (res==F[i]) continue;if (!R[0]){p=i;delta=F[i];R[0]=i;continue;}memcpy(tmp,R,sizeof(tmp));int x=(ll)dec(F[i],res)*qpow(delta,MOD-2)%MOD;R[i-p]=add(R[i-p],x);for (int j=1;j<=las[0];j++) R[i-p+j]=dec(R[i-p+j],(ll)x*las[j]%MOD);R[0]=i+las[0]-p;memcpy(las,tmp,sizeof(las));p=i,delta=dec(F[i],res);}for (int i=1;i<=R[0];i++) printf("%d%c",R[i]," \n"[i==R[0]]);return 0; }總結(jié)
以上是生活随笔為你收集整理的感性理解Berlekamp-Massey算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 郭明錤发布 2024 款苹果 iPad
- 下一篇: 特斯拉 Cybertruck“禁止转售”