• 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;
    }

     

  • 相关阅读:
    怎么把视频变小?
    Java使用HtmlUnit抓取js渲染页面
    范仁义css3课程---2、css代码引入方式
    范仁义css3课程---1、认识css样式
    width和max-width和min-width的区别
    CSS的盒子模型
    css选择器,伪类和伪元素的区别
    CSS选择器详解(总结)
    心得体悟帖---总结-191231(看似明悟)
    css3图片卡片效果
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11462008.html
Copyright © 2020-2023  润新知