[Selected by Shandong Province] Recursive Sequence (Version 2)-Matrix Acceleration

[Selected by Shandong Province] Recursive Sequence (Version 2)

Time limit: 1 Sec Memory limit: 128 MB

Title description

A sequence of natural numbers is defined as follows:

Opposite i <= k: Ai = Bi

Opposite i> k: Ai = C1Ai-1 + C2Ai-2 + …… CkAi-k

Among them, Bj and Cj (1<=j<=k) are given natural numbers. Write a program, given a natural number m<=n, calculate Am+Am+1+……An, and output the value of the remainder of dividing it by the given natural number p.

enter

The first line is the natural number k

The second line includes k natural numbers b1, b2, ... bk.

The third line contains k natural numbers c1, c2,...ck.

The fourth line contains three natural numbers m, n, p.

Output

A positive integer, representing the value of (Am+Am+1+……An)%p

Sample input

2
1 1
1 1
2 10 10003

Sample output

142

prompt

For 100% test data: 1<=k<=15;1<=m<=n<=10^18

For 20% of the test data: 1<=k<=15;1<=m<=n<=10^6

For 30% of the test data: k=1; 1<=m<=n<=10^18

For all test data: 0<=b1,b2,……,bk,c1,c2,……,ck<=10^9;1<=p<=10^8.

answer

From the question, we can know A_{n}=\sum_ {i=1}^{k} C_{i}*A_{n-i}(n>k)that if the sum of A(m~n) is required, we can find s(n)-s(m-1) (prefix sum), so the key recurrence formula is obtained:

S_{n}=S_{n-1}+\sum_ {i=1}^{k} C_{i}*A_{n-i}(n>k)

So we might as well set the initial matrix as [A1 A2 …… Ak Sk],

A_{2}=0*A_{1}+1*A_{2}

A_{3}=0*A_{1}+0*A_{2}+1*A_{3}

……

A_{k}=0+1*A_{k}

A_{k+1}=C_{k}*A_{1}+C_{k-1}*A_{2}+...+C_{1}*A_{k}

S_{k+1}=S_{k}+C_{k}*A_{1}+C_{k-1}*A_{2}+...+C_{1}*A_{k}

So the initial matrix is ​​multiplied by the acceleration matrix of (k+1)*(k+1):

\begin{bmatrix} A_{1} &A_{2} &... &A_{k} &S_{k} \end{bmatrix} * \begin{bmatrix} 0 &0 &... &C_{k} &C_{k} \\ 1 &0 &... &C_{k-1} &C_{k-1} \\ ... &... &... &...&... \\ 0 &0 &... &C_{1} &C_{1} \\ 0 &0 &... &0 & 1 \end{bmatrix} = \begin{bmatrix} A_{2} &A_{3} &... &A_{k+1} &S_{k+1} \end{bmatrix}

Because Ai=Bi(i≤k), it can become

\begin{bmatrix} B_{1} &B_{2} &... &B_{k} &S_{k} \end{bmatrix} * \begin{bmatrix} 0 &0 &... &C_{k} &C_{k} \\ 1 &0 &... &C_{k-1} &C_{k-1} \\ ... &... &... &...&... \\ 0 &0 &... &C_{1} &C_{1} \\ 0 &0 &... &0 & 1 \end{bmatrix} = \begin{bmatrix} A_{2} &A_{3} &... &A_{k+1} &S_{k+1} \end{bmatrix}

and so\begin{bmatrix} B_{1} &B_{2} &... &B_{k} &S_{k} \end{bmatrix} * \begin{bmatrix} 0 &0 &... &C_{k} &C_{k} \\ 1 &0 &... &C_{k-1} &C_{k-1} \\ ... &... &... &...&... \\ 0 &0 &... &C_{1} &C_{1} \\ 0 &0 &... &0 & 1 \end{bmatrix}^{n-k} = \begin{bmatrix} A_{n-k+1} &A_{n-k+2} &... &A_{n} &S_{n} \end{bmatrix}

Use the fast power of two matrices to find Sn and Sm-1 respectively, subtract the two numbers, add p and then %p.

Note that n≤k and m-1≤k can only be calculated by force.

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int k;
ll n,m,p,Sum[20];
struct matrix{
    int n,m;
    ll c[20][20];
    matrix(){memset(c,0,sizeof(c));n=m=0;}
    matrix operator*(const matrix&a){
        matrix r;r.n=n,r.m=a.m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=r.m;j++)
                for(int l=1;l<=m;l++)r.c[i][j]=(r.c[i][j]+c[i][l]*a.c[l][j])%p;
        return r;
    }
    matrix mpow(matrix a,ll b){
        matrix rs;rs.n=rs.m=a.n;
        for(int i=1;i<=rs.n;i++)rs.c[i][i]=1;
        for(;b;b>>=1){
            if(b&1)rs=rs*a;
            a=a*a;
        }
        return rs;
    }
}a,b;
int main()
{
    scanf("%d",&k);
    a.n=1;a.m=k+1;
    b.n=b.m=k+1;
    for(int i=1;i<=k;i++)scanf("%lld",&a.c[1][i]),Sum[i]=Sum[i-1]+a.c[1][i];
    a.c[1][k+1]=Sum[k];
    for(int i=k;i>=1;i--)scanf("%lld",&b.c[i][k]),b.c[i][k+1]=b.c[i][k];
    scanf("%lld%lld%lld",&n,&m,&p);
    for(int i=1;i<k;i++)b.c[i+1][i]=1;
    b.c[k+1][k+1]=1;
    ll x,y;
    if(m>k){
        matrix c=a*b.mpow(b,m-k);
        y=c.c[1][k+1]%p;
    }
    else y=Sum[m]%p;
    if(n-1>k){
        matrix c=a*b.mpow(b,n-1-k);
        x=c.c[1][k+1]%p;
    }
    else x=Sum[n-1]%p;
    printf("%lld",(y-x+p)%p);
    putchar('\n');
    return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43960287/article/details/89310109