bzoj 3231 [ Sdoi 2008 ] 递归数列 —— 矩阵乘法
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3231
裸矩阵乘法。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll K,b[20],c[20],m,n,p,ans1,ans2,s[20]; struct Matrix{ ll a[20][20]; Matrix(){memset(a,0,sizeof a);} void init(){for(int i=1;i<=K+1;i++)a[i][i]=1;} Matrix operator * (const Matrix &y) const { Matrix ret; for(int i=1;i<=K+1;i++) for(int k=1;k<=K+1;k++) for(int j=1;j<=K+1;j++) (ret.a[i][j]+=a[i][k]*y.a[k][j])%=p; return ret; } }f,g; Matrix pw(Matrix a,ll b) { Matrix ret; ret.init(); for(;b;b>>=1ll,a=a*a) if(b&1)ret=ret*a; return ret; } void print(Matrix x) { for(int i=1;i<=K+1;i++) { for(int j=1;j<=K+1;j++) printf("%d",x.a[i][j]); printf("\n"); } } int main() { scanf("%lld",&K); for(int i=1;i<=K;i++)scanf("%lld",&b[i]),f.a[1][i]=b[i],s[i]=s[i-1]+b[i]; f.a[1][K+1]=s[K-1]; for(int i=1;i<=K;i++)scanf("%lld",&c[i]); scanf("%lld%lld%lld",&m,&n,&p); for(int i=1;i<K;i++)g.a[i+1][i]=1; for(int i=1;i<=K;i++)g.a[i][K]=c[K-i+1]; g.a[K][K+1]=g.a[K+1][K+1]=1; if(n<=K)ans1=s[n]%p; else { Matrix aa=f*pw(g,n-K+1); ans1=aa.a[1][K+1]; } if(m-1<=K)ans2=s[m-1]%p; else { Matrix aa=f*pw(g,m-K); ans2=aa.a[1][K+1]; } printf("%lld\n",((ans1-ans2)%p+p)%p);// return 0; }