Berlekamp-Massey 算法

整了个比较精简的线性递推之后算是敢写各种需要线性递推的东西了。

这玩意的用处是求数列的最短线性递推式。实际上的用途一般就是打表。有时候也可以素质二连 O(k2+klogklogn) 水过一些题(举个例子 joke3579 的 P8979 就是明白告诉你这是个线性递推)(joke3579 怒 d zhoukangyang)

Berlekamp-Massey 算法

设数列是 {a1,a2,,an},只考虑 {a1,,ai} 的递推式是 Ri。那么我们每次顺序往下扫一个数,此时可以计算 ai 和用 Ri1 推出来的数之差,记作 deli1。那么我们要求出 Ri,需要:

  1. 如果 del=0,那显然不用动。
  2. 如果 Ri1 是空的,那么初始化放上去 i0
  3. 对于剩下的情况,我们对 Ri1 的系数进行调整。可以找到之前最短的一个 Rw,然后构造 R={0,0,,0,deli1delw,deli1delw×Rw}0iw2 个。那么使得 Ri=Ri1+R 就是新的递推式。证明继续不会。

其实挺好背的。

void BM(int a[],int n,vector<int>&ans){
    int w=0,del=0;
    vector<int>lst;
    for(int i=1;i<=n;i++){
        int tmp=0;
        for(int j=0;j<ans.size();j++)tmp=(tmp+1ll*a[i-j-1]*ans[j])%mod;
        if((a[i]-tmp+mod)%mod==0)continue;
        if(!w){
            w=i;del=(a[i]-tmp+mod)%mod;
            for(int j=i;j;j--)ans.push_back(0);
            continue;
        }
        vector<int>now=ans;
        int mul=1ll*(a[i]-tmp+mod)*qpow(del,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]-1ll*mul*lst[j]%mod+mod)%mod;
        if(now.size()-i<lst.size()-w){
            lst=now;w=i;del=(a[i]-tmp+mod)%mod;
        }
    }
}
posted @   gtm1514  阅读(90)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示