[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; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步