[luoguP2461] [SDOI2008]递归数列(DP + 矩阵优化)

传送门

 

本题主要是构造矩阵,我们只需要把那一段式子看成两个前缀和相减, 然后就直接矩阵连乘。

直接对那个k+1阶矩阵快速幂即可,注意初始化矩阵为单位矩阵,即主对角线(左上到右下)都为1其他都为0。

另外,很多量要开long long。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <cstdio>
#include <cstring>
#define LL long long
 
int k;
LL b[21], c[21], n, m, p;
 
struct Matrix
{
    int n, m;
    LL a[21][21];
    Matrix()
    {
        n = m = 0;
        memset(a, 0, sizeof(a));
    }
}sum, sum1, sum2, t;
 
inline Matrix operator * (Matrix x, Matrix y)
{
    int i, j, k;
    Matrix ans;
    ans.n = x.n;
    ans.m = y.m;
    for(i = 1; i <= x.n; i++)
        for(j = 1; j <= y.m; j++)
            for(k = 1; k <= y.n; k++)
                ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
    return ans;
}
 
inline Matrix operator ^ (Matrix x, LL y)
{
    int i;
    Matrix ans;
    ans.n = ans.m = k + 1;
    for(i = 1; i <= k + 1; i++) ans.a[i][i] = 1;
    for(; y; y >>= 1)
    {
        if(y & 1) ans = ans * x;
        x = x * x;
    }
    return ans;
}
 
int main()
{
    int i;
    scanf("%d", &k);
    for(i = 1; i <= k; i++) scanf("%lld", &b[i]);
    for(i = 1; i <= k; i++) scanf("%lld", &c[i]);
    scanf("%lld %lld %lld", &m, &n, &p);
    for(i = 1; i <= k; i++) b[i] %= p, c[i] %= p;
    sum.n = sum.m = k + 1;
    sum.a[1][1] = 1;
    for(i = 3; i <= k + 1; i++) sum.a[i][i - 1] = 1;
    for(i = 2; i <= k + 1; i++) sum.a[1][i] = sum.a[2][i] = c[i - 1];
    t.n = k + 1;
    t.m = 1;
    for(i = 2; i <= k + 1; i++)
    {
        t.a[i][1] = b[k - i + 2];
        t.a[1][1] = (t.a[1][1] + b[i - 1]) % p;
    }
    if(n - k > 0)
        sum1 = (sum ^ (n - k)) * t;
    else for(i = 1; i <= n; i++)
        sum1.a[1][1] = (sum1.a[1][1] + b[i]) % p;
    if(m - k - 1 > 0)
        sum2 = (sum ^ (m - k - 1)) * t;
    else for(i = 1; i < m; i++)
        sum2.a[1][1] = (sum2.a[1][1] + b[i]) % p;
    printf("%lld\n", ((sum1.a[1][1] - sum2.a[1][1]) % p + p) % p);
    return 0;
}

  

posted @   zht467  阅读(154)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示