zoukankan      html  css  js  c++  java
  • BM算法学习笔记

    BM算法学习笔记

    CSP前就要多学学乱搞(确信)

    myy的论文里引进了BM算法,可以(n^2)求出齐次线性递推式

    学习于大佬的博客:

    https://www.cnblogs.com/zhouzhendong/p/Berlekamp-Massey.html

    https://www.cnblogs.com/zzqsblog/p/6877339.html

    本文没有易证易得,符号非常初等,请放心食用。

    我们要求的递推式形如

    [forall m< ileq n,a_i=sum_{j=1}^m a_{i-j}b_j ]

    (b_i)即为递推式系数。

    考虑增量法,设(R[i])表示当前的 (b),对于新的一个要求(a_i),有两种情况:

    1. 不用更改,此时(a_i=sum_{j=1}^m a_{i-j}R[i][j])
    2. 需要更改递推式,考虑构造递推式的减量递推式(F)

    (Delta_i=a_i-sum_{j=1}^m a_{i-j}R[i][j]) 为当前(i)计算出多的部分,则减量(F)需要满足:

    1. [forall |R'|<k<i,sum_{j=1}^{|F_j|}a_{k-j}F_j=0 ]

    2. [sum_{j=1}^{|F_j|}a_{i-j}F_j=Delta_i ]

    (F)需要满足计算(a_k(k<i))的时候都是0,而计算(a_i)的时候是(Delta_i),才能使减去之后(Delta'=0)

    如果之前没出现过需要更改的情况,直接搞上(i)个0一定是合法的。(其实也只会在(i=1)出现)

    否则直接用前面某个(id)(R_{id})来构造(F)。对于(R_{id}),由于定义,其满足

    [sum_{j=1}^{|R_{id}|}a_{id-j}R_{id}-a_{id}=Delta_{id} ]

    那么我们把它除以(Delta_{id}),乘上(Delta_i),再等效替换出 (i)

    [sum_{j=1}^{|R_{id}|}a_{i-(i-id)-j}frac{R_{id}[j]}{Delta_{id}}-frac{a_{id}}{Delta_{id}}=1\ sum_{j=1}^{|R_{id}|}a_{i-(i-id)-j}frac{R_{id}[j]Delta_i}{Delta_{id}}-frac{a_{id}Delta_i}{Delta_{id}}=Delta_i ]

    那么原来的第(j)位变成了第(i-id+j)位,相当于右移了(i-id)位,再在前面放上一个(-frac{Delta_i}{Delta_{id}})。而对于 (k<id) 都是(sum_j a_{k-j}R_{id}[j]-a_k)等于0的情况,这些情况也还是0,因为乘除对0没有影响。这样我们就构造出了满足要求的(F)

    那么当前的答案就是(R_{i})减去(F)。注意(R_i)并不需要加F,因为后面还要用。

    总结一下,减量F等于

    [left{overbrace{0,0,cdots,0}^{i-id-1个0},-frac{Delta_i}{Delta_{id}},frac{R_{id}[1]Delta_i}{Delta_{id}},frac{R_{id}[2]Delta_i}{Delta_{id}},cdots ight} ]

    那么id选哪个呢?我们要求的是最短递推式(不然整(n)个0也行),那么选(i-id+|R_{id}|)最小的就行了。每次就比较一下(-i+|R_i|)更新(id),具体看代码实现。

    zzq博客的例子比较生动形象,我就不再造了。

    #include<bits/stdc++.h>
    using namespace std;
    int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x; 
    } 
    #define ll long long
    #define FOR(i,a,b) for(int i=a;i<=b;i++) 
    typedef long double ld;
    const int N = 3021;
    const int mod = 1e9+7;
    int n,pn=0;
    ll R[N],Rn[N];
    int rl,nl;
    ll a[N],dlt[N];
    ll tp[N],tl;
    int ksm(int a,int b){
    	int res=1; 
    	while(b){
    		if(b&1){
    			res=1ll*res*a%mod;
    		}a=1ll*a*a%mod;b>>=1;
    	}
    	return res;
    }
    const ld eps = 1e-7;
    int main(){
    	n=read();
    	FOR(i,1,n) scanf("%lld",&a[i]);
    	int id=0,mi=0;
    	FOR(i,1,n){
    		ll dlti=(mod-a[i])%mod;
    		for(int j=1;j<=rl;j++){
    			dlti=(dlti+1ll*a[i-j]*R[j]%mod)%mod;
    		}
    		dlt[i]=dlti;
    		if(dlti==0) continue;
    		if(i==1){
    			rl=1;R[1]=Rn[1]=0;id=1;nl=rl=1;mi=0;continue;
    		}else{
    			FOR(j,1,rl) tp[j]=R[j];tl=rl; //备份R 
    			int tmp=1ll*dlti*ksm(dlt[id],mod-2)%mod;
    			FOR(j,1,nl) R[i-id+j]=(R[i-id+j]-1ll*Rn[j]*tmp%mod+mod)%mod;   //计算F、R 
    			R[i-id]=(R[i-id]+tmp)%mod;
    			rl=max(rl,i-id+nl);
    			if(tl-i<mi) mi=tl-i;nl=tl;FOR(j,1,tl) Rn[j]=tp[j];id=i; //更新Rn 
    		}
    	}
    	while(R[rl]==0) rl--;
    	printf("%d
    ",rl);
    	FOR(i,1,rl){
    		printf("%ld ",R[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    jQuery 自执行函数
    IRelationalOperator空间关系接口简介
    9.2 空间拓扑运算[转]
    解决关于ArcGIS10.2服务手动启动的问题
    Multipart to single part feature
    Multipart polyline to single part lines
    VS2015 C#6.0 中的没有实现/支持的特性
    VS2015 C#6.0 中的那些新特性
    ArcGIS中各种合并要素(Union、Merge、Append、Dissolve)的异同点分析 转载
    FME2010 案例分析: 动态批量转换
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/13927902.html
Copyright © 2011-2022 走看看