P2461 [SDOI2008]递归数列
纪念不看题解\(A\)掉的第一个矩阵快速幂
先做完模板题吧p1939
矩阵开\((k+1)^2\),定义函数\(f_x\)为\(\sum\limits_{i=1}^xa_i\),显然\(f_x=f_{x-1}+a_i\)
\(a_{i-1},a_{i-2}.....a_{i-k},f_{i-1}\) \(\Longrightarrow\) \(a_i,a_{i-1}.....a_{i-k+1},f_i\)
提示到此结束了,仔细想想,相信你能构造出矩阵
My complete code
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
inline LL Read(){
LL x=0,f=1; char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
const LL maxn=51;
struct mat{
LL m[maxn][maxn];
}a,base,st,r;
LL K,m,n,ans1,ans2,ans,MOD,sum;
LL b[maxn],c[maxn];
inline mat Mul(const mat &x,const mat &y){
mat res;
memset(res.m,0,sizeof(res.m));
for(LL i=1;i<=K+1;++i)
for(LL j=1;j<=K+1;++j)
for(LL k=1;k<=K+1;++k)
res.m[i][j]=(res.m[i][j]+(x.m[i][k]*y.m[k][j])%MOD)%MOD;
return res;
}
inline void Pow(LL mi){
while(mi){
if(mi&1)
st=Mul(st,a);
a=Mul(a,a);
mi>>=1;
}
}
int main(){
K=Read();
for(LL i=1;i<=K;++i)
b[i]=Read(),
sum+=b[i];
for(LL i=1;i<=K;++i)
c[i]=Read();
m=Read(),n=Read(),MOD=Read();
if(n>K){
for(LL i=1;i<=K;++i)
a.m[i][1]=a.m[i][K+1]=c[i];
for(LL i=1;i<K;++i)
a.m[i][i+1]=1;
a.m[K+1][K+1]=1;
for(LL i=1;i<=K+1;++i)
st.m[i][i]=1;
Pow(n-K);
for(LL i=1;i<=K;++i)
r.m[1][i]=b[K-i+1]; r.m[1][K+1]=sum;
r=Mul(r,st);
ans1=r.m[1][K+1];
}else
for(LL i=1;i<=n;++i)
ans1=(ans1+b[i])%MOD;
if(m-1>K){
memset(a.m,0,sizeof(a.m));
memset(st.m,0,sizeof(st.m));
memset(r.m,0,sizeof(r.m));
for(LL i=1;i<=K;++i)
a.m[i][1]=a.m[i][K+1]=c[i];
for(LL i=1;i<K;++i)
a.m[i][i+1]=1;
a.m[K+1][K+1]=1;
for(LL i=1;i<=K+1;++i)
st.m[i][i]=1;
Pow(m-1-K);
for(LL i=1;i<=K;++i)
r.m[1][i]=b[K-i+1]; r.m[1][K+1]=sum;
r=Mul(r,st);
ans2=r.m[1][K+1];
}else
for(LL i=1;i<m;++i)
ans2=(ans2+b[i])%MOD;
ans=(ans1-ans2+MOD)%MOD;
printf("%lld",ans);
return 0;
}/*
2
1 1
1 1
2 10 1000003
142
*/