zoukankan      html  css  js  c++  java
  • P2461 [SDOI2008]递归数列

    P2461 [SDOI2008]递归数列

    纪念不看题解(A)掉的第一个矩阵快速幂

    先做完模板题吧p1939

    矩阵开((k+1)^2),定义函数(f_x)(sumlimits_{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
    */
    
  • 相关阅读:
    elasticSearch 查询 bool
    elasticSearch 查询 term
    elasticSearch 查询 match
    python re
    vue day1
    mysql 报错记录
    node.js vue.js 安装
    mysql 插入数据 ,存在跳过
    打印乘法口诀表
    初步使用分支、循环判断数字大小
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10182151.html
Copyright © 2011-2022 走看看