BM递推

Posted profish

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BM递推相关的知识,希望对你有一定的参考价值。

从别的大佬处看到的模板

#include<bits/stdc++.h>
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pqueue priority_queue
#define NEW(a,b) memset(a,b,sizeof(a))
#define Pii pair<int,int>
#define VI vector<int>
const double pi=4.0*atan(1.0);
const double e=exp(1.0);
const int maxn=3e6+8;
typedef long long LL;
typedef unsigned long long ULL;
const LL mod=1e9+7;
const ULL base=1e7+7;
using namespace std;
LL qpow(LL a,LL b){
    LL ans=1;
    a%=mod;
    while(b){
        if(b&1){ans=ans*a%mod;}
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
LL n;
namespace linear_seq{
    const int N=10010;
    LL res[N],base[N],_c[N],_md[N];
    VI Md;
    void mul(LL *a,LL *b,int k){
        for(int i=0;i<k+k;i++) _c[i]=0;
        for(int i=0;i<k;i++) if(a[i]) for (int j=0;j<k;j++) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
        for(int i=k+k-1;i>=k;i--) if(_c[i])
            for(int j=0;j<(int)(Md).size();j++) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
        for(int i=0;i<k;i++) a[i]=_c[i];
    }
    int solve(LL n,VI a,VI b){
        LL ans=0,pnt=0;
        int k=(int)(a).size();
        assert((int)(a).size()==(int)(b).size());
        for(int i=0;i<k;i++) _md[k-1-i]=-a[i];_md[k]=1;
        Md.clear();
        for (int i=0;i<k;i++) if (_md[i]!=0) Md.push_back(i);
        for (int i=0;i<k;i++) res[i]=base[i]=0;
        res[0]=1;
        while((1ll<<pnt)<=n) pnt++;
        for(int p=pnt;p>=0;p--){
            mul(res,res,k);
            if((n>>p)&1){
                for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                for (int j=0;j<(int)(Md).size();j++) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
            }
        }
        for(int i=0;i<k;i++) ans=(ans+res[i]*b[i])%mod;
        if(ans<0) ans+=mod;
        return ans;
    }
    VI BM(VI s){
        VI C(1,1),B(1,1);
        int L=0,m=1,b=1;
        for(int n=0;n<(int)(s).size();n++){
            LL d=0;
            for(int i=0;i<L+1;i++) d=(d+(LL)C[i]*s[n-i])%mod;
            if(d==0) ++m;
            else if(2*L<=n) {
                VI T=C;
                LL c=mod-d*qpow(b,mod-2)%mod;
                while ((int)(C).size()<(int)(B).size()+m) C.push_back(0);
                for (int i=0;i<(int)(B).size();i++) C[i+m]=(C[i+m]+c*B[i])%mod;
                L=n+1-L; B=T; b=d; m=1;
            } else {
                LL c=mod-d*qpow(b,mod-2)%mod;
                while ((int)(C).size()<(int)(B).size()+m) C.push_back(0);
                for (int i=0;i<(int)(B).size();i++) C[i+m]=(C[i+m]+c*B[i])%mod;
                ++m;
            }
        }
        return C;
    }
    int gao(VI a,LL n){
        VI c=BM(a);
        c.erase(c.begin());
        for(int i=0;i<(int)(c).size();i++) c[i]=(mod-c[i])%mod;
        return solve(n,c,VI(a.begin(),a.begin()+(int)(c).size()));
    }
};
int main(){
    int t;
    for(scanf("%d",&t);t;t--){
        scanf("%lld",&n);
        printf("%d
",linear_seq::gao(VI{1,3,5,7},n-1));
    }
}

 

以上是关于BM递推的主要内容,如果未能解决你的问题,请参考以下文章

BM-线性递推板子

杜教BM模板(用于求线性递推公式第N项)

BM递推杜教版

BM求递推式模板

HDU - 6172:Array Challenge (BM线性递推)

线性递推规律BM杜教