Description

一个由自然数组成的数列按下式定义:
对于i <= k:ai = bi
对于i > k: ai = c1ai-1 + c2ai-2 + … + ckai-k
其中bj和 cj (1<=j<=k)是给定的自然数。写一个程序,给定自然数m <= n, 计算am + am+1 + am+2 + … + an, 并输出它除以给定自然数p的余数的值。
Input

由四行组成。
第一行是一个自然数k。
第二行包含k个自然数b1, b2,…,bk。
第三行包含k个自然数c1, c2,…,ck。
第四行包含三个自然数m, n, p。
Output

仅包含一行:一个正整数,表示(am + am+1 + am+2 + … + an) mod p的值。
Sample Input

2

1 1

1 1

2 10 1000003

Sample Output

142
HINT

对于100%的测试数据:

1<= k<=15

1 <= m <= n <= 1018

Source

矩阵快速幂。
我们只需要把那一段式子看成两个前缀和相减。
然后就可以用矩乘了.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
#define MAXN 20
using namespace std;
int K;
LL b[20],c[20];
LL m,n,p;
LL ans;
struct matrix
{
    LL a[MAXN][MAXN];
    matrix(){memset(a,0,sizeof(a));}
    friend matrix operator *(matrix A,matrix B)
    {
        matrix ret;
        for (int i = 1; i <= K + 1; i ++)
            for (int j = 1; j <= K + 1; j ++)
                for (int k = 1; k <= K + 1; k ++)
                    ret.a[i][j] = (ret.a[i][j] + A.a[i][k] * B.a[k][j]) % p;
        return ret;
    }
    friend matrix operator ^(matrix x,LL k)
    {
        matrix ret;
        for (int i = 1; i <= K + 1; i ++) 
            ret.a[i][i] = 1;
        for (LL i = k; i; i >>= 1,x = x * x)
            if (i & 1) ret = ret * x; 
        return ret;
    }
}tmp1,tmp2;
LL solve(LL x)
{
    if (!x) return tmp2.a[1][K+1];
    matrix T=tmp1^x;
    T=tmp2*T;
    return T.a[1][K+1];
}
int main()
{
    scanf("%d",&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);
    for (int i = 1; i <= K; i ++)
        b[i] %= p,c[i] %= p,b[K + 1] += b[i], b[K + 1] %= p;
    for (int i = 1; i <= K; i ++)  
        tmp1.a[i][1] = tmp1.a[i][K + 1] = c[i];
    for (int i = 2; i <= K; i ++)  
        tmp1.a[i - 1][i] = 1;
    tmp1.a[K + 1][K + 1] = 1;
    for (int i = 1; i <= K; i ++)  
        tmp2.a[1][i] = b[K - i + 1];
    tmp2.a[1][K+1] = b[K+1];
    if (n <= K)
    {
        for (int i = m; i <= n; i ++)
            ans += b[i],ans %= p;
        printf("%lld\n",ans);
        return 0;
    }
    ans = solve(n - K);
    if (m <= K)
        for (int i = 1; i < m; i ++)   
            ans -= b[i];
    else    ans -= solve(m - K - 1);
    ans = (ans + p) % p;
    cout<<ans<<endl;
}