请阅读本文的同学们注意:之前这篇博客和所附代码有点问题,求的不一定是最短递推式,非常抱歉

看毛爷爷的论文大概断断续续看了一个月了,看得不是很懂,google了一波好像很快就看懂了,就先口胡一下这个算法好了。这篇文章的介绍方式大概和毛爷爷的论文不大一致,当然算法的本质是一致的。

参考链接:https://grocid.net/2012/11/22/berlekamp-massey-algorithm-explained/

Berlekamp-Massey算法是用来求一个数列的递推式的。

我现在有一个序列$x_1,x_2...x_n$,首先我们先来定义递推式。序列x的递推式是个序列$p_1,p_2...p_m$。一个合法递推式满足对于$i\geq{m+1}$,$x_i=\sum_{j=1}^mp_jx_{i-j}$。一个递推式的次数定义为m,注意这里的每个p都可以为0。

我们定义一个递推式带入一个序列的第i项所得的结果为$\sum_{j=1}^mx_{i-j}p_j-x_i$,如果$i\leq{m}$定义为0。那么合法递推式就是带进去每一项都得0的递推式对吧。

好,现在我们想要求递推式。怎么求呢,我们开始随便口胡一个递推式,就{}好了。

我们考虑第一个数,这样一个一个往下考虑。我们看看现在这个多项式满不满足x[i],满足就留着。

如果不满足,我们就要想办法修复这个递推多项式对吧。

一种naive的想法就是说我开始有个递推多项式为g,它对于前i-1项全成立,到了第i项挂了。我们来算算这个递推式带进第i项,假设是s,那么我们要想办法把带进去得到的值减去s。

如果我们凭空变出一个递推式f,它满足这个递推式带进前i-1项全为0,带进第i项是1,那么我们只要把g减去sf不就行了吗。

如果我们不是第一次遇到这种情况,那么我们之前也曾经有一个递推式,它满足前j-1项,带进去恰好在第j项不为0,不妨假设在第j项为1,如果不为1除掉即可。那么我们只要在这个递推式稍微移一移项,前面补若干个0就可以得到f了。

如果有多个满足条件的递推式?那么我们选择最近的一个肯定最优。

我们可以维护当前最优的一个递推式,使得它补完0之后的长度最少,取这个就行了。

我们来举个例子,我有一个数列1,2,4,10,24,50,116。

我们一个一个数考虑,首先数列里啥都没有,递推式是{}。

然后看到一个1,一脸懵逼,那么递推式随便写一个{0}好了。

接下来我们发现到了2这里挂了。之前1挂掉的经历告诉我们x[1]=1,那么我们令f={1},我们把递推式改成{2}好了。

接下来到了4,我们发现一切良好。

到了10,我们发现又挂了,带进去这项得到了-2。之前2挂的经历告诉我们x[2]=2,那么我们令f={0,0.5,0},把递推式加上2f={0,1,0},那么递推式变成了{2,1,0}。(注意这里结尾有一个0,因为之前递推式里面是{0})

到了24,一切良好。

到了50,我们发现又挂了,带进去得到了8。之前10挂的经历告诉我们-x[4]+2x[3]=-2,那么两边除以-2,0.5x[4]-x[3]=1,所以可以令f={0,0.5,-1},那么8f={0,4,-8},所以递推式要减去8f,变成了{2,-3,8}。

到了116,又挂掉了,带进去得到了-8。之前50的狗带经历告诉我们-x[6]+2x[5]+x[4]=8,那么两边除以8得到-0.125x[6]+0.25x[5]+0.125x[4]=1,那么令f={-0.125,0.25,0.125,0},8f={-1,2,1,0},那么递推式要加上8f,变成{1,-1,9,0}(这里结尾的0是因为原来带了一个0)。

实际程序写起来还是挺简单的。

  1. int n,pn=,fail[];
  2. typedef vector<ld> vld;
  3. vld ps[]; ld x[],delta[];
  4. int main()
  5. {
  6. scanf("%d",&n);
  7. for(int i=;i<=n;i++) scanf("%lf",x+i);
  8. int best=;
  9. for(int i=;i<=n;i++)
  10. {
  11. ld dt=-x[i];
  12. for(int j=;j<ps[pn].size();j++)
  13. dt+=x[i-j-]*ps[pn][j];
  14. delta[i]=dt;
  15. if(fabs(dt)<=1e-) continue;
  16. fail[pn]=i; if(!pn) {ps[++pn].resize(i); continue;}
  17. vld&ls=ps[best]; ld k=-dt/delta[fail[best]];
  18. vld cur; cur.resize(i-fail[best]-); //trailing 0
  19. cur.pb(-k); for(int j=;j<ls.size();j++) cur.pb(ls[j]*k);
  20. if(cur.size()<ps[pn].size()) cur.resize(ps[pn].size());
  21. for(int j=;j<ps[pn].size();j++) cur[j]+=ps[pn][j];
  22. if(i-fail[best]+(int)ps[best].size()>=ps[pn].size()) best=pn;
  23. ps[++pn]=cur;
  24. }
  25. for(unsigned g=;g<ps[pn].size();g++)
  26. cout<<ps[pn][g]<<" "; puts("");
  27. }

什么,卡空间?只有两项是有用的,可以滚动数组。

由于某种原因,具体应用下一篇再说好了。下一篇鸽了

那么Berlekamp-Massey算法有啥用呢?比如我有一个优秀的dp,f[i][j]表示某种神奇的量,然后对1<=i<=n,j<=m,$f[i][j]=\sum_s f[i-1][s]*val[j][s]$,val是与i无关的量,然后要求f[n][1]之类的。以前我们用矩阵快速幂,现在我们就可以用BM算出f[n][1]的递推式,然后闷声m^2logn。

以下附赠一个素质二连板子:

  1. const int MOD=1e9+;
  2. ll qp(ll a,ll b)
  3. {
  4. ll x=; a%=MOD;
  5. while(b)
  6. {
  7. if(b&) x=x*a%MOD;
  8. a=a*a%MOD; b>>=;
  9. }
  10. return x;
  11. }
  12. namespace linear_seq {
  13. inline vector<int> BM(vector<int> x)
  14. {
  15. vector<int> ls,cur;
  16. int pn=,lf,ld;
  17. for(int i=;i<int(x.size());++i)
  18. {
  19. ll t=-x[i]%MOD;
  20. for(int j=;j<int(cur.size());++j)
  21. t=(t+x[i-j-]*(ll)cur[j])%MOD;
  22. if(!t) continue;
  23. if(!cur.size())
  24. {cur.resize(i+); lf=i; ld=t; continue;}
  25. ll k=-t*qp(ld,MOD-)%MOD;
  26. vector<int> c(i-lf-); c.pb(-k);
  27. for(int j=;j<int(ls.size());++j) c.pb(ls[j]*k%MOD);
  28. if(c.size()<cur.size()) c.resize(cur.size());
  29. for(int j=;j<int(cur.size());++j)
  30. c[j]=(c[j]+cur[j])%MOD;
  31. if(i-lf+(int)ls.size()>=(int)cur.size())
  32. ls=cur,lf=i,ld=t;
  33. cur=c;
  34. }
  35. vector<int>&o=cur;
  36. for(int i=;i<int(o.size());++i)
  37. o[i]=(o[i]%MOD+MOD)%MOD;
  38. return o;
  39. }
  40. int N; ll a[SZ],h[SZ],t_[SZ],s[SZ],t[SZ];
  41. inline void mull(ll*p,ll*q)
  42. {
  43. for(int i=;i<N+N;++i) t_[i]=;
  44. for(int i=;i<N;++i) if(p[i])
  45. for(int j=;j<N;++j)
  46. t_[i+j]=(t_[i+j]+p[i]*q[j])%MOD;
  47. for(int i=N+N-;i>=N;--i) if(t_[i])
  48. for(int j=N-;~j;--j)
  49. t_[i-j-]=(t_[i-j-]+t_[i]*h[j])%MOD;
  50. for(int i=;i<N;++i) p[i]=t_[i];
  51. }
  52. inline ll calc(ll K)
  53. {
  54. for(int i=N;~i;--i) s[i]=t[i]=;
  55. s[]=; if(N!=) t[]=; else t[]=h[];
  56. for(;K;mull(t,t),K>>=) if(K&) mull(s,t); ll su=;
  57. for(int i=;i<N;++i) su=(su+s[i]*a[i])%MOD;
  58. return (su%MOD+MOD)%MOD;
  59. }
  60. inline int gao(vector<int> x,ll n)
  61. {
  62. if(n<int(x.size())) return x[n];
  63. vector<int> v=BM(x); N=v.size(); if(!N) return ;
  64. for(int i=;i<N;++i) h[i]=v[i],a[i]=x[i];
  65. return calc(n);
  66. }
  67. }

你可以用这个数据来测试你的BM板子:https://files.cnblogs.com/files/zzqsblog/BM-data.zip (mod 1e9+7,最短长度为712或713)

就先更到这里吧。

Berlekamp-Massey算法简单介绍的更多相关文章

  1. 算法笔记_071:SPFA算法简单介绍(Java)

    目录 1 问题描述 2 解决方案 2.1 具体编码   1 问题描述 何为spfa(Shortest Path Faster Algorithm)算法? spfa算法功能:给定一个加权连通图,选取一个 ...

  2. 垃圾回收算法简单介绍——JVM读书笔记&lt;二&gt;

    垃圾回收的过程主要包含两部分:找出已死去的对象.移除已死去的对象. 确定哪些对象存活有两种方式:引用计数算法.可达性分析算法. 方案一:引用计数算法 给对象中加入一个引用计数器.每当有一个地方引用它时 ...

  3. 算法笔记_068:Dijkstra算法简单介绍(Java)

    目录 1 问题描述 2 解决方案 2.1 使用Dijkstra算法得到最短距离示例 2.2 具体编码   1 问题描述 何为Dijkstra算法? Dijkstra算法功能:给出加权连通图中一个顶点, ...

  4. Paxos算法简单介绍

    一种基于消息传递且具有高度容错特性的一致性算法.解决在存在宕机或者网络异常的集群中对某个数据的值达成一致性,并且保证无论在发生以上任何异常都不会破坏整个系统的一致性,具有容错性. Paxos算法实现的 ...

  5. 算法笔记_070:BellmanFord算法简单介绍(Java)

    目录 1 问题描述 2 解决方案 2.1 具体编码   1 问题描述 何为BellmanFord算法? BellmanFord算法功能:给定一个加权连通图,选取一个顶点,称为起点,求取起点到其它所有顶 ...

  6. 算法笔记_069:Floyd算法简单介绍(Java)

    目录 1 问题描述 2 解决方案 2.1 使用Floyd算法得到最短距离示例 2.2 具体编码   1 问题描述 何为Floyd算法? Floyd算法功能:给定一个加权连通图,求取从每一个顶点到其它所 ...

  7. PrincetonUniversity-Coursera 算法:算法简单介绍

    Course Overview What is this course? Intermediate-level survey course. Programming and proble solvin ...

  8. Berlekamp Massey算法求线性递推式

    BM算法求求线性递推式   P5487 线性递推+BM算法   待AC.   Poor God Water   // 题目来源:ACM-ICPC 2018 焦作赛区网络预赛 题意   God Wate ...

  9. 简单介绍一下R中的几种统计分布及常用模型

    统计学上分布有很多,在R中基本都有描述.因能力有限,我们就挑选几个常用的.比较重要的简单介绍一下每种分布的定义,公式,以及在R中的展示. 统计分布每一种分布有四个函数:d――density(密度函数) ...

随机推荐

  1. MVC异步方法

    在mvc的开发过程中,有时候我们会需要在action中调用异步方法,这个时候会需要做一些特殊处理.我们会使用到await和async.对应的controller也应该是async的. 在MVC4中直接 ...

  2. Laravel 5.2数据库--多个关联关系,带条件约束的渴求式加载的问题

    ### 今天在连表获取数据的时候,老是获取不到想要的,确实有点无力适从的感觉. 归根到底,还是对laravel不够熟悉,至少是数据库操作那块. ### 问题是这样的: 我想要通过连表中间表,拿中间表的 ...

  3. 【原创】大数据基础之Hive(5)hive on spark

    hive 2.3.4 on spark 2.4.0 Hive on Spark provides Hive with the ability to utilize Apache Spark as it ...

  4. windows IDEA注册码激活方法(2018.4.8)靠谱可用!

    简介 intellij idea 2018注册码是针对intellij idea 2018软件研发推出,它的使用需要和激活补丁一起使用,安装包里面也拥有破解补丁, 所有无需在进行单独的下载:不过如果选 ...

  5. Python 三种过滤去重方法

    SET集合去重 set(1,1,2) REDIS去重 布隆过滤器

  6. 洛谷P5162 WD与积木 [DP,NTT]

    传送门 思路 真是非常套路的一道题-- 考虑\(DP\):设\(f_n\)为\(n\)个积木能搭出的方案数,\(g_n\)为所有方案的高度之和. 容易得到转移方程: \[ \begin{align*} ...

  7. LuoGu P2420 让我们异或吧

    其实......这就是个SB题,本来看到这个题,和树上路径有关 于是--我就欣喜地打了一个树剖上去,结果嘞,异或两遍等于没异或 所以这题和LCA屁关系都没有,所以这题就是个树上DFS!!!! 所以它为 ...

  8. JVM·垃圾收集器与内存分配策略之垃圾收集器!

    1.Serial(串行)收集器(新生代都采用复制算法)     这是个单线程的收集器:即 当他工作的时候,会停掉虚拟机所有的线程!(Stop The World)

  9. NPOI写Excel,Spire.XLS for.NET组件转换Excel为PDF

    首先要引用NPOI动态库和Microsoft.Office.Interop.excel.dll (Microsoft.Office.Interop.excel.dll  最好使用使用NuGet下载 , ...

  10. leetcode(js)算法89之格雷编码

    格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异. 给定一个代表编码总位数的非负整数 n,打印其格雷编码序列.格雷编码序列必须以 0 开头 示例 1: 输入: 2 输出: [ ...