@ZCDHJ
2019-08-07T09:45:50.000000Z
字数 1341
阅读 432
未分类
枚举最后一个出现的数字来计算 ,那么 ,很显然可以矩阵加速。设转移矩阵为 ,对于 ,因为 ,以及矩阵满足分配率,枚举最后一个断点,, 表示的是所有 矩阵的和,直接递推计算即可。总复杂度 。
#include <iostream>
#include <cstdio>
#include <cstring>
const int MAXN = 500;
const int MOD = 998244353;
int n, m;
char s[MAXN + 2];
struct Matrix {
int a[6][6];
Matrix() {
memset(a, 0, sizeof(a));
}
friend Matrix operator* (const Matrix &lhs, const Matrix &rhs) {
Matrix res;
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= m; ++j)
for (int k = 1; k <= m; ++k)
res.a[i][j] = (1LL * res.a[i][j] + 1LL * lhs.a[i][k] * rhs.a[k][j]) % MOD;
return res;
}
friend Matrix operator+ (const Matrix &lhs, const Matrix &rhs) {
Matrix res;
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= m; ++j)
res.a[i][j] = (lhs.a[i][j] + rhs.a[i][j]) % MOD;
return res;
}
void out() {
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= m; ++j) printf("%d ", a[i][j]);
printf("\n");
}
}
void init() {
for (int i = 1; i <= m; ++i) a[i][i] = 1;
}
} dp[MAXN | 1], d[MAXN | 1][10];
int main() {
scanf("%s", s + 1);
scanf("%d", &m);
n = strlen(s + 1);
for (int i = 1; i <= m; ++i) {
d[0][1].a[i][m] = 1;
if (i > 1) d[0][1].a[i][i - 1] = 1;
}
dp[0].a[1][m] = 1;
for (int i = 0; i <= n; ++i) {
for (int j = 1; j < 10; ++j) {
if (i == 0 && j == 1) continue;
if (j == 1) d[i][j] = d[i - 1][9] * d[i - 1][1];
else d[i][j] = d[i][j - 1] * d[i][1];
}
}
s[0] = '0';
for (int i = 1; i <= n; ++i) {
Matrix now;
now.init();
for (int j = i - 1; j >= 0; --j) {
if (s[j + 1] != '0') {
now = now * d[i - 1 - j][s[j + 1] - '0'];
}
dp[i] = dp[i] + (dp[j] * now);
}
}
printf("%d\n", dp[n].a[1][m] % MOD);
return 0;
}