此博客是抄論文的,你可以認爲是轉載的
1.線性遞推數列
有限數列顯然是線性遞推數列。
無限數列設其生成函數爲
那麼如果能被表示爲的形式,其中,則是線性遞推數列。
常數項爲是因爲遞推式你要讓來遞推出所以常數項需要爲。
能這樣表示是因爲線性遞推實質上就是,其中是我們的線性遞推式。
對於一個線性遞推數列,假設他前項的最短遞推式是,長度爲,那麼如果不是前項的最短遞推式,那麼有,且這個等號是可以通過構造取到的。
首先顯然,如果的話:
實在不知道怎麼用語言表示交換和號。
也就是說如果那麼原來的遞推式必可以繼續用。
接下來我們給出在不是前項的遞推式時的構造方案,也就是算法。
也就是說每次增長遞推式,我們都可以用這個方法使得增長時,不增長時。
因爲上文證明了,所以這個算法對於有限長度的數列求出的遞推式一定是最短的。
對於無限長的數列,
所以我們只需要取最短遞推式長度的兩倍即可。
邊界情況:第一次增長遞推式的時候,應該是第一個非元素,那麼個即爲前個數的最短遞推式,也就是根本沒有遞推,同時也滿足。
線性遞推求第項:
代碼:luogu【模板】Berlekamp-Massey算法
(真的很短。)
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define maxn 10005
#define pb push_back
#define vi vector<int>
#define mod 998244353
using namespace std;
int n,m,a[maxn];
int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod;return r; }
vi BM(int *a,int n){ // a[0 ~ n] is used
vi r(1,1),p(1,0),t;int lt;
rep(i,0,n){
int d=0;
rep(j,0,r.size()-1) d = (d + r[j] * 1ll * a[i-j]) % mod;
if(!d) continue;
t = r;
r.resize(max(p.size() , i+1-(p.size()-1)));
rep(j,0,p.size()-1) r[j+i-lt] = (r[j+i-lt] - 1ll * d * p[j]) % mod;
int iv = Pow(d , mod-2);
p = t , lt = i;
rep(i,0,p.size()-1) p[i] = 1ll * p[i] * iv % mod;
}
return r; // a \times r = const
}
typedef vi poly;
poly Mul(const poly &A,const poly &B,const poly &P){
poly r(A.size() + B.size() - 1);
rep(i,0,A.size()-1) rep(j,0,B.size()-1) r[i+j] = (r[i+j] + 1ll * A[i] * B[j]) % mod;
per(i,r.size()-1,P.size()-1) if(r[i]){// in this problem P[P.size()-1] = 1 , so there is no need to getinv.
int t = r[i];
rep(j,1,P.size())
r[i-j+1] = (r[i-j+1] - 1ll * P[P.size()-j] * t) % mod;
}
r.resize(P.size()-1);
return r;
}
int main(){
scanf("%d%d",&n,&m);
rep(i,0,n-1) scanf("%d",&a[i]);
vi P = BM(a,n-1);
rep(i,1,P.size()-1) printf("%d%c",(mod-(P[i]+mod)%mod) % mod," \n"[i==P.size()-1]);
reverse(P.begin(),P.end());
poly r(1,1),t(2,0);
t[1] = 1;
for(;m;m>>=1,t=Mul(t,t,P)) if(m&1)
r = Mul(r,t,P);
int ans = 0;
rep(i,0,r.size()-1) ans = (ans + 1ll * r[i] * a[i]) % mod;
printf("%d\n",(ans+mod)%mod);
}
向量序列的最短遞推式:
矩陣的零化多項式:使得矩陣:
矩陣的最小多項式:
零化多項式中次數最低的多項式。
如何求矩陣的最小多項式:
直接求的最短遞推式即可,對於稀疏矩陣可以做到。
BM與矩陣的特徵多項式:
特徵多項式是矩陣的一個零化多項式,
而求出的最小多項式也是矩陣的一個零化多項式
最小多項式是特徵多項式的一個因式,因爲如果不是則可以做帶餘除法得到餘式爲更小的零化多項式。
對於一個線性遞推問題,我們可以通過零化多項式得到線性遞推式,所以在解決線性遞推時可以找最小多項式(用BM),也可以求特徵多項式。
但是特徵多項式的最經典的解法是根據定義來求行列式後拉格朗日插值求出多項式,相較於感覺沒有什麼競爭力,儘管特徵多項式有的巧妙解法,但是這個解法無法計算出線性遞推的前項(就是不能用遞推式的部分),有了前項那爲什麼不用呢?
綜上在信息學奧賽的當前時代最小多項式完爆特徵多項式,很多打着特徵多項式的旗子的題目都可以用BM解決。