bzoj 3231 [Sdoi2008]递归数列——矩阵乘法

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3231

矩阵乘法裸题。

1018是10^18。别忘了开long long。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=20;
int n;
ll L,R,b[N],c[N],mod,s[N],prn;
struct Matrix{
    ll a[N][N];
    Matrix(){memset(a,0,sizeof a);}
    void init()
    {
        for(int i=1;i<n;i++)a[i][1]=c[i];
        for(int i=2;i<n;i++)a[i-1][i]=1;
        a[1][n]=a[n][n]=1;
    }
    Matrix operator* (const Matrix &b)const
    {
        Matrix c;
        for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
                for(int j=1;j<=n;j++)
                    (c.a[i][j]+=a[i][k]*b.a[k][j])%=mod;
        return c;
    }
}ans,r,yans,yr;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&b[i]);
        s[i]=s[i-1]+b[i];
        ans.a[1][n-i+1]=b[i];
    }
    ans.a[1][n+1]=s[n-1];
    yans=ans;
    for(int i=1;i<=n;i++)scanf("%lld",&c[i]);
    scanf("%lld%lld%lld",&L,&R,&mod);
    n++;r.init();yr=r;
    if(R<n)prn=s[R];
    else
    {
        ll k=R-n+1;
        while(k)
        {
            if(k&1)ans=ans*r;
            r=r*r;k>>=1ll;
        }
        prn=(ans.a[1][n]+ans.a[1][1])%mod;
    }
    if(L-1<n)prn=((prn-s[L-1])%mod+mod)%mod;
    else
    {
        ll k=L-1-n+1;
        while(k)
        {
            if(k&1)yans=yans*yr;
            yr=yr*yr;k>>=1ll;
        }
        prn=((prn-yans.a[1][n]-yans.a[1][1])%mod+mod)%mod;
    }
    printf("%lld\n",prn);
    return 0;
}

 

posted on 2018-07-27 16:17  Narh  阅读(183)  评论(0编辑  收藏  举报

导航