P2461 [SDOI2008]递归数列

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
*/
posted @ 2018-12-26 22:08  y2823774827y  阅读(136)  评论(0编辑  收藏  举报