常系数其次线性递推

放个板子

#include<iostream>
#include<cstdio>
#define N 100002
using namespace std;
typedef long long ll;
const int mod=1000000007; 
ll a[N],h[N],num[N],ans[N],k,n,tmp[N],p[N];
inline int rd(){
    int x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
inline void mul(ll *a,ll *b,ll *c){
    for(int i=0;i<=2*k;++i)tmp[i]=0;
    for(int i=0;i<k;++i)
      for(int j=0;j<k;++j)tmp[i+j]=(tmp[i+j]+1ll*a[i]*b[j]%mod)%mod;
    for(int i=2*k-2;i>=k;--i){
        for(int j=k-1;j>=0;--j)tmp[i-k+j]=(tmp[i-k+j]-tmp[i]*p[j]%mod+mod)%mod;
        tmp[i]=0;
    }
    for(int i=0;i<k;++i)c[i]=tmp[i];
} 
int main(){
    n=rd();k=rd();
    for(int i=1;i<=k;++i)a[i]=rd();
    for(int i=0;i<k;++i)h[i]=rd();
    p[k]=1;
    for(int i=1;i<=k;++i)p[k-i]=mod-a[i];
    for(int i=k;i<2*k;++i){
        for(int j=1;j<=k;++j)h[i]=(h[i]+h[i-j]*a[j]%mod)%mod;
        h[i]=(h[i]+mod)%mod;
    }
    if(n<2*k){printf("%lld",h[n]);return 0;}
    int b=n-k;
    num[1]=1;ans[0]=1;
    while(b){
        if(b&1)mul(ans,num,ans);
        mul(num,num,num);b>>=1;
    }
    ll res=0;
    for(int i=0;i<k;++i)(res+=h[i+k]*ans[i]%mod)%=mod;;
    cout<<res;
    return 0;
}

 

posted @ 2019-02-26 20:49  comld  阅读(90)  评论(0编辑  收藏  举报