[luoguP2461] [SDOI2008]递归数列(DP + 矩阵优化)
本题主要是构造矩阵,我们只需要把那一段式子看成两个前缀和相减, 然后就直接矩阵连乘。
直接对那个k+1阶矩阵快速幂即可,注意初始化矩阵为单位矩阵,即主对角线(左上到右下)都为1其他都为0。
另外,很多量要开long long。
#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; }