Luogu_P2461 [SDOI2008]递归数列 【题解】 矩阵乘法

题面:https://www.luogu.org/problem/P2461

拿到题面,矩阵快速幂裸题。

开始推矩阵。

推出的矩阵是这个样子:

右边是ans矩阵,左边是base矩阵。具体的可以看代码。

就可以开心的快速幂了!

但是由于求的是m到n之间的。

需要两次。

而且注意判断是不是小于K。

但是!!!最最最重要的!!!!!!!!!!

不要忘了统计答案时候!!!!!

(ans%p+p)%p

调了俩小时!!!!!!!!!!!!!!!!

代码如下:

#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
int k,N,M,p;
ll sum;
int b[20],c[20];
struct node{
    ll m[20][20];
}ans,base;
inline node mul(node x,node y){
    node res;
    memset(res.m,0,sizeof(res.m));
    for(int i=1;i<=k+1;i++)
        for(int t=1;t<=k+1;t++){
            if(!x.m[i][t]) continue;
            for(int j=1;j<=k+1;j++){
                res.m[i][j]+=x.m[i][t]*y.m[t][j];
                res.m[i][j]%=p;
            }
        }
    return res;
}
inline void qp(int t){
    while(t){
        if(t&1) ans=mul(ans,base);
        base=mul(base,base);
        t>>=1;
    }
}
signed main()
{
    scanf("%lld",&k);
    for(int i=1;i<=k;i++)
        scanf("%lld",&b[i]);
    for(int i=1;i<=k;i++)
        scanf("%lld",&c[i]);
    scanf("%lld%lld%lld",&M,&N,&p);

    memset(ans.m,0,sizeof(ans.m));memset(base.m,0,sizeof(base.m));
    for(int i=1;i<=k;i++)
        sum=(sum+b[i])%p;
    ans.m[1][1]=sum;
    for(int i=1;i<=k;i++)
        ans.m[1][i+1]=b[k-(i-1)];
    base.m[1][1]=1;
    for(int i=2;i<=k;i++)
        base.m[i][i+1]=1;
    for(int i=2;i<=k+1;i++)
        base.m[i][1]=c[i-1],base.m[i][2]=c[i-1];
    // for(int i=1;i<=k+1;i++){
    //     for(int j=1;j<=k+1;j++){
    //         cout<<base.m[i][j]<<" ";
    //     }
    //     puts("");
    // }
    // for(int j=1;j<=k+1;j++) cout<<ans.m[1][j]<<endl;
    ll ans1=0;
    if((M-1)<k){
        for(int i=1;i<=M-1;i++)
            ans1=(ans1+b[i])%p;
    }else{
        qp(M-1-k);
        ans1=ans.m[1][1]%p;
    }


    
    memset(ans.m,0,sizeof(ans.m));memset(base.m,0,sizeof(base.m));
    ans.m[1][1]=sum;
    for(int i=1;i<=k;i++)
        ans.m[1][i+1]=b[k-(i-1)];
    base.m[1][1]=1;
    for(int i=2;i<=k;i++)
        base.m[i][i+1]=1;
    for(int i=2;i<=k+1;i++)
        base.m[i][1]=c[i-1],base.m[i][2]=c[i-1];
    ll ans2=0;
    if(N<k){
        for(int i=1;i<=N;i++)
            ans2=(ans2+b[i])%p;
    }else{
        qp(N-k);
        ans2=ans.m[1][1]%p;
    }



    printf("%lld
",((ans2-ans1)%p+p)%p);
    //system("pause");
    return 0;
}

 

原文地址:https://www.cnblogs.com/ChrisKKK/p/11462008.html