十进制矩阵乘法优化DP
十进制矩乘优化DP
P1397
[NOI2013] 矩阵游戏
题目描述
婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的
递推式中
现在婷婷想知道
输入格式
包含一行有六个整数
输出格式
包含一个整数,表示
样例 #1
样例输入 #1
3 4 1 3 2 6
样例输出 #1
85
提示
【样例1说明】
样例中的矩阵为:
1 4 7 10
26 29 32 35
76 79 82 85
数据范围
测试点编号 | 数据范围 |
---|---|
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 |
分析
对于此题,不难发现肯定是矩阵乘法
而我们的矩阵乘法加速递推一般而言是加速的一维数组的递推,对于这个二维数组,我们可以将其编号为一维数组,具体的原来的
那么这道题的递推只与上一个状态有关,所以我们大可以设一个长度为2的数组
此时就是
类似的,在
所以说,由
所以,
至此,便可以使用矩阵快速幂求解
另外,由于
//P1397
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define int long long
//#define scanf scanf_s
using namespace std;
int f[3], a[3][3], b[3][3], a1, b1, c1, d1, n, m;
int c[3][3], d[3][3], e[3][3];
char p[1000500], q[1000500];
#define mod 1000000007
void mul(int a[3][3], int b[3][3]) {
int c[3][3];
memset(c, 0, sizeof c);
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 2; j++) {
for (int k = 1; k <= 2; k++) {
c[i][j] += a[i][k] % mod * b[k][j] % mod;
c[i][j] %= mod;
}
}
}
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 2; j++) {
a[i][j] = c[i][j] % mod;
}
}
}
void mul2(int a[3], int b[3][3]) {
int f[3];
memset(f, 0, sizeof f);
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 2; j++) {
f[j] += a[i] % mod * b[i][j] % mod;
f[j] %= mod;
}
}
for (int i = 1; i <= 2; i++)a[i] = f[i] % mod;
}
void power(int a[3][3], int b) {
int c[3][3];
for (int i = 1; i <= 2; i++)for (int j = 1; j <= 2; j++)c[i][j] = a[i][j] % mod;
b--;
while (b) {
if (b & 1)mul(c, a);
mul(a, a);
b >>= 1;
}
for (int i = 1; i <= 2; i++)for (int j = 1; j <= 2; j++)a[i][j] = c[i][j];
}
void update(char s, int a[3][3]) {
int x = s - '0';
for (int i = 1; i <= x; i++) {
mul(c, a);
}
// printf("%d\n",s-'0');
// for (int i = 1; i <= 2; i++) {
// for (int j = 1; j <= 2; j++)printf("%d ", c[i][j]);
// puts("");
// }
power(a, 10);
// for (int i = 1; i <= 2; i++) {
// for (int j = 1; j <= 2; j++)printf("%d ", a[i][j]);
// puts("");
// }
}
signed main() {
f[1] = f[2] = 1;
scanf("%s %s", p + 1, q + 1);
scanf("%lld%lld%lld%lld", &a1, &b1, &c1, &d1);
a[1][1] = 1, a[1][2] = b1, a[2][2] = a1;
b[1][1] = 1, b[1][2] = d1, b[2][2] = c1;
for (int i = 1; i <= 2; i++)c[i][i] = d[i][i] = 1;
int len1 = strlen(p + 1), len2 = strlen(q + 1);
reverse(p + 1, p + len1 + 1);
reverse(q + 1, q + len2 + 1);
for (int i = 1; i <= len1; i++) {
if (p[i] != '0') {
p[i] -= 1;
break;
}
else {
p[i] = '9';
}
}
if (p[len1] == '0')len1--;
for (int i = 1; i <= len2; i++) {
if (q[i] != '0') {
q[i] -= 1;
break;
}
else {
q[i] = '9';
}
}
if (q[len2] == '0')len2--;
// printf("%d %d\n", len1, len2);
// printf("%c %c\n", q[1], p[1]);
for (int i = 1; i <= len2; i++) {
update(q[i], a);
}
for (int i = 1; i <= 2; i++)
for (int j = 1; j <= 2; j++)d[i][j] = c[i][j];
mul(c, b);
// for (int i = 1; i <= 2; i++) {
// for (int j = 1; j <= 2; j++)printf("%d ", c[i][j]);
// puts("");
// }
for (int i = 1; i <= 2; i++)for (int j = 1; j <= 2; j++)a[i][j] = c[i][j], c[i][j] = 0;
for (int i = 1; i <= 2; i++)c[i][i] = 1;
for (int i = 1; i <= len1; i++) {
update(p[i], a);
}
mul(c, d);
mul2(f, c);
// for (int i = 1; i <= 2; i++) {
// for (int j = 1; j <= 2; j++)printf("%d ", c[i][j]);
// puts("");
// }
// for (int i = 1; i <= 2; i++) {
// for (int j = 1; j <= 2; j++)printf("%d ", d[i][j]);
// puts("");
// }
printf("%lld\n", f[2]);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!