[SDOI2008]递归数列
矩阵加速递推。
图片出处见水印
#include <iostream>
#include <cstdio>
#include <cstring>
#define int long long
using namespace std;
int K,b[20],c[20],m,n,p;
long long sum[20];
struct Matrix {
int g[16][16];
Matrix(){memset(g,0,sizeof g);}
Matrix operator * (const Matrix &rhs) const{
Matrix ans;
for(int i=0;i<=K;i++)
for(int j=0;j<=K;j++)
for(int k=0;k<=K;k++)
(ans.g[i][k]+=g[i][j]*rhs.g[j][k])%=p;
return ans;
}
}A,B;
int ksm(Matrix d,int z) {
Matrix ans=A;
while(z) {
if(z&1) ans=ans*d;
d=d*d;
z>>=1;
}
return ans.g[0][K];
}
main() {
scanf("%lld",&K);
for(int i=0;i<K;i++) scanf("%lld",&b[i]),A.g[0][i]=b[i],A.g[0][K]+=b[i],sum[i]=sum[i-1]+b[i];//cout<<sum[K-1]<<endl<<endl;
for(int i=0;i<K;i++) scanf("%lld",&c[i]);
for(int i=0;i<K;i++) B.g[i+1][i]=1;
for(int i=0;i<K;i++) B.g[i][K-1]=B.g[i][K]=c[K-i-1];
B.g[K][K-1]=0;B.g[K][K]=1;
scanf("%lld%lld%lld",&m,&n,&p);
int C,D;
m-=K+1,n-=K;
if(n<=0) C=sum[n+K-1];
else C=ksm(B,n);
if(m<=0) D=sum[m+K-1];
else D=ksm(B,m);
printf("%lld",(C-D+p)%p);
}