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

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

裸矩阵乘法。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll K,b[20],c[20],m,n,p,ans1,ans2,s[20];
struct Matrix{
    ll a[20][20];
    Matrix(){memset(a,0,sizeof a);}
    void init(){for(int i=1;i<=K+1;i++)a[i][i]=1;}
    Matrix operator * (const Matrix &y) const
    {
        Matrix ret;
        for(int i=1;i<=K+1;i++)
            for(int k=1;k<=K+1;k++)
                for(int j=1;j<=K+1;j++)
                    (ret.a[i][j]+=a[i][k]*y.a[k][j])%=p;
        return ret;
    }
}f,g;
Matrix pw(Matrix a,ll b)
{
    Matrix ret; ret.init();
    for(;b;b>>=1ll,a=a*a)
        if(b&1)ret=ret*a;
    return ret;
}
void print(Matrix x)
{
    for(int i=1;i<=K+1;i++)
    {
        for(int j=1;j<=K+1;j++)
            printf("%d",x.a[i][j]);
        printf("\n");
    }
}
int main()
{
    scanf("%lld",&K); 
    for(int i=1;i<=K;i++)scanf("%lld",&b[i]),f.a[1][i]=b[i],s[i]=s[i-1]+b[i];
    f.a[1][K+1]=s[K-1];
    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++)g.a[i+1][i]=1;
    for(int i=1;i<=K;i++)g.a[i][K]=c[K-i+1];
    g.a[K][K+1]=g.a[K+1][K+1]=1;
    if(n<=K)ans1=s[n]%p;
    else
    {
        Matrix aa=f*pw(g,n-K+1);
        ans1=aa.a[1][K+1];
    }
    if(m-1<=K)ans2=s[m-1]%p;
    else
    {
        Matrix aa=f*pw(g,m-K);
        ans2=aa.a[1][K+1];
    }
    printf("%lld\n",((ans1-ans2)%p+p)%p);//
    return 0;
}

 

posted @ 2018-07-27 17:01  Zinn  阅读(160)  评论(0编辑  收藏  举报