【LOJ】#2128. 「HAOI2015」数字串拆分
题解
题中给的函数可以用矩阵快速幂递推
我们记一个数组dp[i](这个数组每个元素是一个矩阵)表示从1到i所有的数字经过拆分矩阵递推的加和
转移方法是
\(dp[i] = \sum_{j = 0}^{i - 1} dp[j] * tr[j + 1][i]\)
\(tr[j][i]\)表示矩阵的\([j,i]\)组成的数字次幂是什么样的矩阵
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 100005
#define mo 994711
//#define ivorysi
using namespace std;
typedef long long int64;
typedef long double db;
typedef unsigned int u32;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
const int MOD = 998244353;
int M,N;
char s[505];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
struct Matrix {
int f[6][6];
Matrix() {memset(f,0,sizeof(f));}
friend Matrix operator * (const Matrix &a,const Matrix &b) {
Matrix c;
for(int i = 0 ; i < M ; ++i) {
for(int j = 0 ; j < M ; ++j) {
for(int k = 0 ; k < M ; ++k) {
c.f[i][j] = inc(c.f[i][j],mul(a.f[i][k],b.f[k][j]));
}
}
}
return c;
}
friend Matrix operator + (const Matrix &a,const Matrix &b) {
Matrix c;
for(int i = 0 ; i < M ; ++i) {
for(int j = 0 ; j < M ; ++j) {
c.f[i][j] = inc(a.f[i][j],b.f[i][j]);
}
}
return c;
}
}A[15],dp[505],tr[505][505];
int g[15];
Matrix fpow(Matrix x,int c) {
Matrix res = A[0],t = x;
while(c) {
if(c & 1) res = res * t;
t = t * t;
c >>= 1;
}
return res;
}
void Solve() {
scanf("%s",s + 1);
read(M);N = strlen(s + 1);
for(int i = 0 ; i < M ; ++i) {
A[0].f[i][i] = 1;
}
dp[0] = A[0];
g[0] = 1;
for(int i = 1 ; i < M ; ++i) {
for(int j = 1 ; j <= i ; ++j) {
g[i] = inc(g[i - j],g[i]);
}
}
for(int i = 0 ; i < M ; ++i) {
if(i != M - 1) A[1].f[i][i + 1] = 1;
A[1].f[M - 1][i] = 1;
}
for(int i = 2 ; i <= 9 ; ++i) {
A[i] = A[i - 1] * A[1];
}
for(int i = 1 ; i <= N ; ++i) {
Matrix r = A[0],t;
for(int j = i ; j <= N; ++j) {
r = r * r;t = r;
r = r * r;r = r * r;r = r * t;
r = r * A[s[j] - '0'];
tr[i][j] = r;
}
}
for(int i = 1 ; i <= N ; ++i) {
for(int j = 0 ; j < i ; ++j) {
dp[i] = dp[i] + dp[j] * tr[j + 1][i];
}
}
int ans = 0;
for(int i = 0 ; i < M ; ++i) ans = inc(ans,mul(g[i],dp[N].f[0][i]));
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}