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\n",linear_seq::gao(VI{1,3,5,7},n-1));
    }
}

原文地址:https://www.cnblogs.com/Profish/p/9738143.html

时间: 2024-11-06 09:28:29

BM递推的相关文章

杜教BM递推板子

Berlekamp-Massey 算法用于求解常系数线性递推式 #include<bits/stdc++.h> typedef std::vector<int> VI; typedef long long ll; typedef std::pair<int, int> PII; const ll mod = 1000000007; ll powmod(ll a, ll b) { ll res = 1; a %= mod; assert(b >= 0); for(;

BM递推杜教版

#include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (long long i=a;i<n;i++) #define per(i,a,n) for (long long i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #def

BM递推杜教版【扩展】

也就是模数不是质数的时候, //下面的板子能求质数和非质数,只需要传不同的参数. #include <cstdio> #include <cstdlib> #include <cassert> #include <cstring> #include <bitset> #include <cmath> #include <cctype> #include <unordered_map> #include <

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

题意:给出,三个函数,h,b,a,然后T次询问,每次给出n,求sqrt(an); 思路:不会推,但是感觉a应该是线性的,这个时候我们就可以用BM线性递推,自己求出前几项,然后放到模板里,就可以求了. 数据范围在1e15,1000组都可以秒过. 那么主要的问题就是得确保是线性的,而且得求出前几项. #include<bits/stdc++.h> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per

[HDOJ6172] Array Challenge(线性递推,黑科技)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6172 题意:给一堆东西,就是求个线性递推式,求第n项%1e9+7 杜教板真牛逼啊,线性递推式用某特征值相关的论文板,打表前几项丢进去就出结果了. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 #define rep(i,a,n) for (ll i=a;i<n;i++) 6 #def

算法分析中递推式的一般代数解法 张洋

http://blog.codinglabs.org/articles/linear-algebra-for-recursion.html 另介绍一种算法 Berlekamp-Massey算法,常简称为BM算法,是用来求解一个数列的最短线性递推式的算法. #include <bits/stdc++.h> using namespace std; typedef long long ll; const double eps = 1e-7; const int maxn = 1e5 + 5; ve

2018南京区域赛G题 Pyramid——找规律&amp;&amp;递推

先手动推出前10项,再上BM板子求出递推式 $A_n = 5A_{n-1} - 10A_{n-2} + 10A_{n-3} - 5A_{n-4} + A_{n-5}$,根据特征根理论可求出特征方程 $(x-1)^5$,设 $A_n = k_1n^4 + k_2n^3 + k_3n^2+k_4n+k_5$,代入前5项求出系数(用了高斯消元法解方程组). 这样虽然做出来了,但是感觉比较浪费时间,因为BM板子和高斯消元法的板子都不短,对手残狗不友好. 差分 首先前7项分别为1  5 15 35 70

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

hdu 1267 递推

下沙的沙子有几粒? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4326    Accepted Submission(s): 2268 Problem Description 2005年11月份,我们学校参加了ACM/ICPC 亚洲赛区成都站的比赛,在这里,我们获得了历史性的突破,尽管只是一枚铜牌,但获奖那一刻的激动,也许将永远铭刻