线性序列 模版

来源:互联网 发布:ubuntu u盘挂载 编辑:程序博客网 时间:2024/06/05 03:50
typedef long long ll;// 线性序列 求第n项const ll mod=1000000007;ll quick_pow(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}const int N=10010;ll res[N],base[N],_c[N],_md[N];vector<ll> Md;void mul(ll *a,ll *b,int k){    for(int i=0;i<2*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=2*k-1;i>=k;i--)        if(_c[i])            for(int j=0;j<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];}ll solve(ll n,vector<ll> a,vector<ll> b){ // a 系数 b 初值 b[n+1]=a[0]*b[n]+...    //        printf("%d\n",SZ(b));    ll ans=0,pnt=0;    int k=(int)a.size();    assert(a.size()==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=(int)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<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;}vector<ll> BM(vector<ll> s){    vector<ll> C(1,1),B(1,1);    ll L=0,m=1,b=1;    for(int n=0;n<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)        {            vector<ll> T=C;            ll c=mod-d*quick_pow(b,mod-2)%mod;            while(C.size()<B.size()+m) C.push_back(0);            for(int i=0;i<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*quick_pow(b,mod-2)%mod;            while(C.size()<B.size()+m) C.push_back(0);;            for(int i=0;i<B.size();i++) C[i+m]=(C[i+m]+c*B[i])%mod;            m++;        }    }    return C;}ll gao(vector<ll> a,ll n){    vector<ll> c=BM(a);    c.erase(c.begin());    for(int i=0;i<c.size();i++)        c[i]=(mod-c[i])%mod;    return solve(n,c,vector<ll>(a.begin(),a.begin()+c.size()));}int main(){    ll n;    scanf("%lld",&n);    printf("%lld\n",gao(vector<ll>{1,1,2,3,5,8},n-1));}
原创粉丝点击