zoukankan      html  css  js  c++  java
  • BM算法

    BM算法

    用来求解一个数列的递推式。
    即给定({x_i})求解一个({a_i}),满足(|a|=m,x_n=sum_{i=1}^ma_i*x_{n-i})

    考虑增量法构造。
    假设当前有一个长度为(m)({a})满足条件,并且对于(x_{1..n-1})都满足递推关系。
    定义(delta=sum_{i=1}^m a_i*x_{n-i}-x_i)。如果(delta)显然满足递推关系,不用管。
    否则不满足,那么我们就要(fix)一下锅。那么我们就要找另外一个递推式({b}),让(iin[1,n-1])的时候算出来的(delta')都是(0),同时在(i=n)的时候算出来的东西是(1),那么乘一乘,搞一搞就可以了。
    问题在于怎么找这个东西。如果当前这个不是第一次不合法,那么前面必定存在一个位置(j),然后在(j)的时候我们对于这个多项式修了一次锅,它满足了([1,j-1])都是(0),同时(j)位置上有值。那么我们在前面补零,直到当前(i)位置的时候恰好对应到(j)位置上那个非(0)的位置,乘逆元之后,这样子恰好能够满足条件。那么把多项式加在一起就好啦。

    说得好乱啊,看看代码就懂了。

    模板

    void BM()
    {
    	n=read();
    	for(int i=1;i<=n;++i)f[i]=read();
    	for(int i=1;i<=n;++i)
    	{
    		delta[i]=(MOD-f[i])%MOD;
    		for(int j=0,l=now.size();j<l;++j)add(delta[i],1ll*f[i-j-1]*now[j]%MOD);
    		if(!delta[i])continue;fail[cnt]=i;
    		if(!cnt){now.resize(i);++cnt;continue;}
    		int inv=(MOD-1ll*delta[i]*fpow(delta[fail[lst]],MOD-2)%MOD)%MOD,l=pre.size();
    		cur.clear();cur.resize(i-fail[lst]-1);cur.push_back(MOD-inv);
    		for(int j=0;j<l;++j)cur.push_back(1ll*inv*pre[j]%MOD);
    		if(now.size()>cur.size())cur.resize(now.size());
    		for(int j=0,l=now.size();j<l;++j)add(cur[j],now[j]);
    		if(now.size()-i<pre.size()-fail[lst])lst=cnt,pre=now;
    		++cnt;now=cur;
    	}
    	for(int i=0,l=now.size();i<l;++i)printf("%d ",now[i]);
    }
    
  • 相关阅读:
    原生js螺旋运动
    拉美电子游戏市场创收45亿美元
    ZOJ 3229 Shoot the Bullet
    Java的压缩、解压及压缩加密、解密解压 样例
    java环境变量配置
    git在myelispse中的安装
    java注解
    Python测试框架doctest
    python中的协程
    Flask log配置,实现按照日期自动生成日志文件
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10289506.html
Copyright © 2011-2022 走看看