版权声明:这篇文章的作者是个蒟蒻,没有转载价值,如果要转说一下好了 https://blog.csdn.net/litble/article/details/81783267
显然强大的Rayment已经讲得很清楚了:这里
因为这东西我可能明天就忘了,所以写一下。
大概就是构造一个多项式
(
是美丽的转移系数)。对于线性齐次递推的转移矩阵
,设有
,又由于
所以
然后用类似快速幂的方法搞这个东西,得到多项式
的系数。
那么有
,两边同时乘初始向量
(下标代表该向量代表的每一项里最大项是
)得到:
,即
然后多项式乘法和取模都暴力搞即可。多项式取模的暴力搞就是竖式除法,由于
的最高次项为1,所以这个竖式除法还是很好写的。
#include<bits/stdc++.h>
using namespace std;
#define RI register int
const int N=4005,mod=1000000007;
int a[N],h[N],r[N],ans[N],g[N],c[N];
int n,K,res;
int qm(int x) {return x>=mod?x-mod:x;}
void mul(int *a,int *b) {
for(RI i=0;i<=2*K-2;++i) c[i]=0;
for(RI i=0;i<K;++i)
for(RI j=0;j<K;++j)
c[i+j]=qm(c[i+j]+1LL*a[i]*b[j]%mod);
for(RI i=2*K-2;i>=K;--i)
for(RI j=K-1;j>=0;--j)
c[i-K+j]=qm(c[i-K+j]-1LL*c[i]*g[j]%mod+mod);
//直接乘以c[i]是因为g的最高次项系数为1
for(RI i=0;i<K;++i) a[i]=c[i];
}
int main()
{
scanf("%d%d",&n,&K);
for(RI i=1;i<=K;++i) scanf("%d",&a[i]),a[i]=qm(a[i]+mod);
for(RI i=0;i<K;++i) scanf("%d",&h[i]),h[i]=qm(h[i]+mod);
g[K]=1;for(RI i=1;i<=K;++i) g[K-i]=mod-a[i];
for(RI i=K;i<=2*K-1;++i)
for(RI j=1;j<=K;++j) h[i]=qm(h[i]+1LL*h[i-j]*a[j]%mod);
if(n<=2*K-1) {printf("%d\n",h[n]);return 0;}
r[1]=ans[0]=1;
for(RI i=n-K+1;i;i>>=1,mul(r,r)) if(i&1) mul(ans,r);
for(RI i=0;i<K;++i) res=qm(res+1LL*ans[i]*h[K-1+i]%mod);
printf("%d\n",res);
return 0;
}