BZOJ3231 SDOI2008 递归数列 矩阵乘法

题意:设an=c1an-1+c2an-2+……+ckan-k,sn=a1+a2+……+an。给定a1到ak与c,求sn-sm-1

题解:以k=3为例\[\left( {\begin{array}{*{20}{c}}
{{a_{n - 2}}}&{{a_{n - 1}}}&{{a_n}}&{{s_n}}
\end{array}} \right) = \left( {\begin{array}{*{20}{c}}
{{a_1}}&{{a_2}}&{{a_3}}&{{s_3}}
\end{array}} \right){\left( {\begin{array}{*{20}{c}}
0&0&{{c_3}}&{{c_3}}\\
1&0&{{c_2}}&{{c_2}}\\
0&1&{{c_1}}&{{c_1}}\\
0&0&0&1
\end{array}} \right)^{n - 3}}\]

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long

const int MAXN=16+2;
int K;
ll b[MAXN],c[MAXN],Sum[MAXN],Ans1,Ans2,P,M,N;
struct Matrix{
    int l,r;
    ll Mat[MAXN][MAXN];

    Matrix(){}
    Matrix(int _l,int _r):l(_l),r(_r){ memset(Mat,0,sizeof(Mat));}
    Matrix operator*(Matrix t){
        Matrix Ret=Matrix(l,t.r);
        for(int i=1;i<=l;i++)
        for(int j=1;j<=t.r;j++)
        for(int k=1;k<=r;k++)
            Ret.Mat[i][j]=(Ret.Mat[i][j]+Mat[i][k]*t.Mat[k][j]%P)%P;
        return Ret;
    }
    Matrix operator^(ll p){
        Matrix t=Matrix(l,r),Ret=Matrix(l,r);
        memcpy(t.Mat,Mat,sizeof(Mat));

        if(p&1) memcpy(Ret.Mat,Mat,sizeof(Mat));
        else
            for(int i=1;i<=l;i++) Ret.Mat[i][i]=1;

        while(p>>=1){
            t=t*t;
            if(p&1) Ret=Ret*t;
        }
        return Ret;
    }
}Int,Tran;

int main(){
    cin >> K;
    Int=Matrix(1,K+1);
    for(int i=1;i<=K;i++){
        scanf("%lld",b+i);
        Int.Mat[1][i]=b[i];
    }
    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++) Sum[i]=(Sum[i-1]+b[i])%P,Int.Mat[1][i]%=P,c[i]%=P;

    if(N<=K){
        cout << (Sum[N]-Sum[M-1]+P)%P << endl;
        return 0;
    }

    Tran=Matrix(K+1,K+1);
    for(int i=1;i<=K;i++) Tran.Mat[i][K]=Tran.Mat[i][K+1]=c[K-i+1];
    for(int i=2;i<=K;i++) Tran.Mat[i][i-1]=1;
    Tran.Mat[K+1][K+1]=1,Int.Mat[1][K+1]=Sum[K];

    if(M>K) Ans1=(Int*(Tran^(M-K-1))).Mat[1][K+1];
    else Ans1=Sum[M-1];
    Ans2=(Int*(Tran^(N-K))).Mat[1][K+1];
    cout << (Ans2-Ans1+P)%P << endl;

    return 0;
}
View Code

 

posted @ 2017-03-25 10:42  WDZRMPCBIT  阅读(228)  评论(0编辑  收藏  举报