传送门
常系数齐次线性递推学习
学习了任意模数多项式乘除法
O
(
n
2
)
O(n^2)
O(n2)。除法就是手动模拟大除法。
需要的东西就是一个转移矩阵
A
A
A的特征多项式。
要把
A
n
A^{n}
An看做是一个只有一项的
n
n
n次多项式。
然后知道初始的那几个就可以推出来了。
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
typedef std::vector<int> poly;
cs int mod=1e9+7;
cs int K=2e3+5;
namespace IO{
cs int Rlen=1<<22|1;
char buf[Rlen],*p1,*p2;
inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
template <typename T>
inline T get(){
char ch=gc();T x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=0;ch=gc();}
while(isdigit(ch)) x=(x+(x<<2)<<1)+(ch^48),ch=gc();
return f?x:mod-x;
}
inline int gi(){return get<int>();}
inline ll gl(){return get<ll>();}
}
using IO::gi;
using IO::gl;
int n,k,h[K],a[K];
poly T;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int quickpow(int a,int b,int ret=1){for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
inline int inv(int x){return quickpow(x,mod-2);}
inline void Add(int &x,int y){x=(x+y>=mod)?x+y-mod:x+y;}
inline void Dec(int &x,int y){x=(x-y<0)?x-y+mod:x-y;}
inline void Mul(int &x,int y){x=1ll*x*y%mod;}
inline poly operator*(poly A,poly B){
int len=A.size()+B.size()-2;
poly C(len+1,0);
for(int re i=0;i<A.size();++i)
for(int re j=0;j<B.size();++j)
Add(C[i+j],mul(A[i],B[j]));
return C;
}
inline poly operator%(poly A,poly B){
//len为最高次次数
int lenA=A.size()-1,lenB=B.size()-1,Inv=inv(B[lenB]);
if(lenA<lenB) return A;
for(int re i=lenA;i>=lenB;--i) if(A[i]){
int t=mul(A[i],Inv);
for(int re j=i;j>=i-lenB;--j)
Dec(A[j],mul(t,B[lenB-i+j]));
}return A.resize(lenB+1),A;
}
inline poly quickpow(poly A,int b){
poly ret(1,1);
for(;b;b>>=1,A=(A*A)%T) if(b&1) ret=(ret*A)%T;
return ret;
}
int out;
int main(){
// freopen("bzoj4161.in","r",stdin);
n=gi(),k=gi(),T.resize(k+1),T[k]=1;
for(int re i=1;i<=k;++i) a[i]=gi();
for(int re i=0;i< k;++i) h[i]=gi();
for(int re i=0;i< k;++i) T[i]=dec(0,a[k-i]);
poly ans={0,1};ans=quickpow(ans,n);
for(int re i=0;i<ans.size();++i) Add(out,mul(ans[i],h[i]));
printf("%d\n",out);
}