首页 > 其他分享 >Berlekamp_Massey与常系数齐次线性递推

Berlekamp_Massey与常系数齐次线性递推

时间:2023-06-11 22:45:09浏览次数:45  
标签:Massey dots int sum Berlekamp Delta 线性 递推

Berlekamp_Massey

BM线性递推,看了这篇博客才学会的:[link]((29条消息) [学习笔记]Berlekamp-Massey算法_cz_xuyixuan的博客-CSDN博客) 。这里稍微记录一下做法,符号和下表尽量精细。

假设有序列 \(\{a_1,a_2,\dots,a_n\}\) ,称序列 \(\{r_1,r_2,\dots ,r_m\}\) 为线性递推式,当且仅当 \(\forall m+1\leq i\leq n,a_i=\sum_{j=1}^{m}r_ja_{i-j}\) 。

BM算法就是要找到一个最短的线性递推式。

考虑使用增量法,假设目前已经构造了 \(\{a_1,a_2,\dots ,a_{i-1}\}\) 的线性递推式,然后加入 \(a_i\) 构造新的线性递推式。由于线性递推式会修改若干次,那么把每一次修改得到的线性递推式记录下来,记作 \(\{R_0,\dots ,R_{c}\}\) ,其中 \(R_{c}\) 就是最新的线性递推式,初值是 \(c=0,R_0=\{\}\) ,记 \(m_i\) 表示 \(R_i\) 的长度。

具体的构造方案如下:

令 \(\Delta_{c,i}=a_i-\sum_{j=1}^{m_c}R_{c,j}a_{i-j}\) 。

首先检验 \(R_{c}\) 在 \(a_i\) 是否满足线性递推,如果 \(\Delta_{c,i}=0\) 那么说明满足,不需要进行修改。

如果 \(\Delta_{c,i}\ne 0\) ,说明需要修正了,如果 \(c=0\) 说明 \(a_i\) 是第一个非零数,那么直接令 \(c=1,R_1=\{0,\dots,0\}\) ,其中 \(0\) 的个数为 \(i\) ,这样 \(m_1\geq i\) ,不需要在任何位置判断。

否则记录错位位置 \(p_c=i\) ,表示线性递推式 \(R_c\) 在位置 \(p_c\) 第一次出错了,然后尝试使用构造一个修正用的线性递推式 \(r'\) ,使其满足 \(\forall m'+1\leq k<i,\sum_{j=1}^{m'}r'_ja_{k-j}=0\) 并且 \(\sum_{j=1}^{m'}r'_ja_{i-j}=\Delta_{c,i}\) ,就是说把修正线性递推式加上之后不影响前面的递推值,并且能把 \(\Delta_{c,i}\) 补回来。

尝试使用 \(R_{c-1}\) 来构造 \(r'\) ,可以证明是必定有解的。

令 \(v=\frac{\Delta_{c,i}}{\Delta_{c-1,p_{c-1}}}\) ,构造 \(r'=\{0,\dots,0,v,-vR_{c-1,1},\dots ,-cR_{c,m_c}\}\) ,其中 \(0\) 的个数为 \(i-p_{c-1}-1\) ,后面的部分是 \(v\{1,-R_{c-1}\}\) 。

简单计算一下这个 \(r'\) 在各个位置上的贡献。对于 \(\Delta_i\) 来说,前面的 \(i-p_{c-1}-1\) 个 \(0\) 把 \(a_{p_{c-1}+1,\dots i-1}\) 的贡献给抹掉了,后面其实是 \(v\Delta_{c-1,p_{c-1}}\) ,那么就是说 \(\Delta_i=v\Delta_{c-1,p_{c-1}}=\Delta_{c,i}\) ,正好就补上了。再考虑另外一个限制,由于 \(r'\) 中有 \(i-p_{c-1}-1\) 个前导 \(0\) ,并且 \(i\) 已经判断过了,所以实际上要判断的是 \(v\{1,-R_{c-1}\}\) 能否在 \(k\leq p_{c-1}-1\) 的位置上满足 \(=0\) 的要求,这个显然是满足的,因为 \(k<p_{c-1}\) 的位置都可以用 \(R_{c-1}\) 来递推。

所以就构造出了一个可行的 \(r'\) ,再令 \(R_{c+1}=r'+R_c\) ,其中 \(+\) 是对位加,就构造出了能够线性递推 \(\{a_1,\dots,a_i\}\) 的线性递推式 \(R_{c+1}\) 。

想要最短可以观察 \(r'\) 的长度和什么有关,可以发现 \(m'=i-p_t-1+1+m_t=i-p_t+m_t\) ,那么只需要取 \(m'\) 最小的 \(t\) 即可,并不需要强制 \(t=c-1\) ,只需要 \(t>0\) 即可。

常系数齐次线性递推

思路是把每个 \(a_n\) 都用 \(\{a_1,\dots,a_k\}\) 来表示,即把 \(\{a_1,\dots ,a_k\}\) 看作一个基底,根据上面 BM 的知识,可以知道 \(k=m_c\) 。

常系数齐次线性递推需要用到这样的一个性质:若 \(a_n=\sum_{i=1}^{k}p_ia_i\) ,那么 \(a_{n+m}=\sum_{i=1}^{k}p_ia_{i+m}\) ,这个是比较显然的,证明直接换元即可。

那么考虑如果已经知道了 \(a_n=\sum_{i=1}^{k}p_ia_i,a_m=\sum_{i=1}^{k}q_ia_i\) ,通过这些信息计算 \(a_{n+m}\) 。

具体如下:

\[a_{n+m}=\sum_{i=1}^{k}p_ia_{i+m}=\sum_{i=1}^{k}p_i\sum_{j=1}^{k}q_ja_{i+j} \]

先用一次卷积计算出 \(a_{1,\dots ,2k}\) 的系数,然后用线性递推式把 \(a_{k+1,\dots ,2k}\) 的系数还原到 \(a_{1,\dots ,k}\) 上即可。

知道这个之后直接倍增做就好了,若要求 \(a_w\) 时间复杂度为卷积的复杂度乘 \(\log w\) ,即 \(O(k^2\log w)\) 或 \(O(k\log k \log w)\)。


洛谷上的版题的代码如下:

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
inline void add(int &x,int y){if ((x+=y)>=mod) x-=mod;}
inline void sub(int &x,int y){if ((x-=y)<0) x+=mod;}
inline int Mod(int x){return x>=mod?x-mod:x;}
inline int ksm(int x,int y){int res=1;for (;y;y>>=1,x=1ll*x*x%mod) if (y&1) res=1ll*res*x%mod;return res;}
int R[10005][5005],m[10005],p[10005],r[5005],d[10005],c=0;
int a[10005];
int n,w;
int ans[5005],base[5005],t[10005];
void mul(int *a,int *b,int *c,int k){
	for (int i=1;i<=2*k;++i) t[i]=0;
	for (int i=1;i<=k;++i)
		for (int j=1;j<=k;++j)
			add(t[i+j],1ll*a[i]*b[j]%mod);
	for (int i=2*k;i>k;--i)
		for (int j=1;j<=k;++j)
			add(t[i-j],1ll*t[i]*r[j]%mod);
	for (int i=1;i<=k;++i) c[i]=t[i];
}
void ksm(int *ans,int *base,int y,int k){
	ans[1]=base[1]=1;
	while (y){
		if (y&1) mul(ans,base,ans,k);
		mul(base,base,base,k);
		y>>=1;
	}
}
int main(){
	scanf("%d%d",&n,&w);
	for (int i=1;i<=n;++i) scanf("%d",&a[i]);
	for (int i=1;i<=n;++i){
		int delta=a[i];
		for (int j=1;j<=m[c];++j) sub(delta,1ll*R[c][j]*a[i-j]%mod);
		if (!delta) continue;
		p[c]=i,d[c]=delta;
		if (!c){
			m[1]=i;
			for (int j=1;j<=i;++j) R[1][j]=0;
			++c;
		}
		else{
			int t=c-1;
			for (int j=c-2;j>=1;--j)
				if (-p[j]+m[j]<-p[t]+m[t]) t=j;
			int v=1ll*delta*ksm(d[t],mod-2)%mod;
			for (int j=1;j<=i-p[t]-1;++j) r[j]=0;
			r[i-p[t]]=v;
			for (int j=1;j<=m[t];++j) r[i-p[t]+j]=Mod(mod-1ll*R[t][j]*v%mod);
			m[c+1]=max(i-p[t]+m[t],m[c]);
			for (int j=1;j<=m[c+1];++j) R[c+1][j]=Mod(R[c][j]+r[j]);
			++c;
		}
	}
	for (int i=1;i<=m[c];++i) printf("%d ",R[c][i]);puts("");
	for (int i=1;i<=m[c];++i) r[i]=R[c][i];
	ksm(ans,base,w,m[c]);
	int sum=0;
	for (int i=1;i<=m[c];++i) add(sum,1ll*ans[i]*a[i]%mod);
	printf("%d\n",sum);
	return 0;
}

标签:Massey,dots,int,sum,Berlekamp,Delta,线性,递推
From: https://www.cnblogs.com/jerryjiang/p/17473787.html

相关文章

  • 动态规划三:常见状态与常见递推关系式
    动态规划三:常见递推关系式常见状态坐标型前缀划分型前缀匹配型区间型背包型常见状态坐标型dp[i]:从起点到坐标i的最值/方案数/可行性dp[i][j]:从起点到坐标i,j的最值/方案数/可行性 前缀划分型dp[i]:前i个字符的最值/方案数/可行性dp[i][j]:前i个字符划分为j个部分的......
  • P8933 [JRKSJ R7] 技巧性的块速递推 题解
    题目传送门题意:简单来说就是一个涂色游戏。有一个n×m的棋盘需要涂色。每格只能涂黑色或白色两种颜色。横、竖、斜连续3格颜色不能相同。横、竖、斜连续4格颜色不能有3个相同颜色,即只能是2个黑和2个白。最后让你统计出所有符合条件的涂色方式的方......
  • 矩阵快速幂加速递推
    矩阵优化递推的思想在于把递推的层数化为矩阵的幂数,也就是说设计一个矩阵\(A\),使得\(A^n\)中的某个元素就是递推的第\(n\)项,即\(f_n\)。这么做就可以将\(O(n)\)的递推优化为\(O(\log_2n)\)的矩阵快速幂(矩阵\(A\)的行列数为常数,因此快速幂中的矩阵乘法复杂度为常数),本质......
  • m基于Berlekamp-Massey钱搜索算法的BCH译码误码率matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下: 2.算法涉及理论知识概要      BCH编译码是一种纠错能力强,构造简单的信道编译码。BCH编译码的生成多项式可以由如下的式子表示: ①BCH码是一种纠错码、线性分组码、循环码。 ②需要传输信息位数:k ③纠错能力:t ④总......
  • 递推
    递推斐波那契数列的使用:f(n)=f(n-1)+f(n-2)经常会出现初始值不同而为此数列的情况 城市路径(P352):给出n个城市的二维坐标,d=|xa-xb|+|ya-yb|.你可以跳过一个城市,求跳过后从1到n城市的最小总距离。Ans=min(f(i-1)+g(i+1)+d(i-1,i+1))//f(i)为前个城市距离之和,g(i)为i到n城市距......
  • Python 2-03 递推和递归
    递推和递归一、递推算法Recursionmethod递推算法是通过已知条件,利用特定关系得出中间推论,直至得到结果的算法。递推算法分为顺推和逆推两种。动态规划1、顺推法所谓顺推法是从已知条件出发,逐步推算出要解决的问题的方法叫顺推。#n!阶乘deffactorial(n):t=1fori......
  • generator 1(矩阵优化递推式+10倍增优化)
     x1,bx2(开始值) ......
  • 该模型基于id=0控制 ,通过电机的基本数学模型对其定子电阻R, 永磁磁链ψf, dq轴电感Ls进
    该模型基于id=0控制,通过电机的基本数学模型对其定子电阻R,永磁磁链ψf,dq轴电感Ls进行递推最小二乘法辨识,仿真结果表明了该方法的有效性ID:8330669177527757......
  • 基于一阶RC模型,电池带遗忘因子递推最小二乘法+扩展卡尔曼滤波算法(FFRLS+ EKF),参数与SOC
    基于一阶RC模型,电池带遗忘因子递推最小二乘法+扩展卡尔曼滤波算法(FFRLS+EKF),参数与SOC的在线联合估计,matlab程序YID:76100659957301925......
  • 一阶RC模型自适应遗忘因子递推最小二乘法+扩展卡尔曼滤波算法AFFRLS+EKF锂电池参数和S
    一阶RC模型自适应遗忘因子递推最小二乘法+扩展卡尔曼滤波算法AFFRLS+EKF锂电池参数和SOC联合估计遗忘因子可随时间自适应变化,不再是定值,提高估计精度matlab程序参考文献ID:52100675009205808......