[HAOI2015] numeric string split - dp, matrix multiplication

Has a length \ (n-\) string of numbers, defined \ (f (S) \) is the \ (S \) split into several \ ([1, m] \ ) the number of programs and the number of . Now, you can use this sequence is divided into a plurality of digital numbers (allowing leading \ (0 \) ) and adding, require that all programs \ (F \) and. \ (n \ leq 500, m \ leq 5 \)

Solution

Set \ (f [i] \) of \ (I \) is the number of split, then clearly \ (f [i] = \ sum_ {j = 1} ^ mf [ij] \)

Obviously this stuff in matrices transfer vector construct \ (V_I = (F [I], F [I-. 1], \ DOTS, F [IM]) ^ T \) , may be provided
\ [A = \ begin {bmatrix} 1 & 1 & 1 & \ dots & 1 \\ 1 & 0 & 0 & \ dots & 0 \\ 0 & 1 & 0 & \ dots & 0 \\ \ dots & \ dots & \ dots & \ dots & \ dots \\ 0 & 0 &
0 & \ dots & 0 \ end {bmatrix} \] and thus the transfer equation may be described as \ (I-V_I = Av_. 1} {\) , further, \ (A = V_n nv_0 ^ \) , where \ (v_0 = (1,0, \ dots, 0) ^ T \)

We can pre-out \ (P [I] [J] = A ^ {I \ J} CDOT 10 ^ \) , it is now for the string \ (a_i \) , its \ (A ^ S = \ prod_ {i = 1} ^ k P [a_i ] [ki] \)

Set \ (g [i] \) represents the processing of the string \ (I \) program by adding a matrix corresponding to the position, the answer is \ (g [n] \) of the first row and first column, and \ (G [0] = the I \) , consider the transfer
\ [\ begin {aligned} g [i] & = \ sum_ {j = 0} ^ {i-1} g [j] \ cdot A ^ {s [j + 1, i]} \ end
{aligned} \] and \ (a \) of the power terms may be backwards recursion, i.e.
\ [a ^ {s [j , i]} = a ^ {s [j + 1, i]} P [s_j ] [ij] \]

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int mod = 998244353;
const int N = 505;

struct matrix {
    int a[7][7]={};
    int n,m;
    void print() {
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) {
                cout<<a[i][j]<<", ";
            }
            cout<<endl;
        }
    }
};

matrix I(int n) {
    matrix ret;
    ret.n=n;
    ret.m=n;
    for(int i=1;i<=n;i++) ret.a[i][i]=1;
    return ret;
}

matrix operator * (matrix a, matrix b) {
    matrix ret;
    ret.n = a.n;
    ret.m = b.m;
    for(int i=1;i<=ret.n;i++) {
        for(int j=1;j<=ret.m;j++) {
            for(int k=1;k<=a.m;k++) {
                ret.a[i][j] += a.a[i][k] * b.a[k][j];
                ret.a[i][j] %= mod;
                ret.a[i][j] += mod;
                ret.a[i][j] %= mod;
            }
        }
    }
    return ret;
}

matrix operator + (matrix a, matrix b) {
    matrix ret;
    ret.n = a.n;
    ret.m = a.m;
    for(int i=1;i<=ret.n;i++) {
        for(int j=1;j<=ret.m;j++) {
            ret.a[i][j] = (a.a[i][j] + b.a[i][j] + mod) % mod;
        }
    }
    return ret;
}

int n,m;
char s[N];

matrix p[12][N],g[N],a[N][N];

signed main() {
    ios::sync_with_stdio(false);
    cin>>s+1;
    n=strlen(s+1);
    for(int i=1;i<=n;i++) s[i]-='0';
    cin>>m;
    p[0][0]=I(m);
    p[1][0].n=m;
    p[1][0].m=m;
    for(int i=1;i<=m;i++) p[1][0].a[1][i]=1;
    for(int i=2;i<=m;i++) p[1][0].a[i][i-1]=1;
    for(int j=0;j<=n;j++) {
        p[0][j]=I(m);
        if(j>0) p[1][j]=p[9][j-1]*p[1][j-1];
        for(int i=2;i<=9;i++) p[i][j]=p[i-1][j]*p[1][j];
    }
    for(int i=1;i<=n;i++) {
        a[i+1][i]=I(m);
        for(int j=i;j>=1;--j) a[j][i]=a[j+1][i]*p[s[j]][i-j];
    }
    g[0]=I(m);
    for(int i=1;i<=n;i++) {
        g[i].n=g[i].m=m;
        for(int j=0;j<i;j++) {
            g[i]=g[i]+g[j]*a[j+1][i];
        }
    }
    cout<<g[n].a[1][1];
}

Guess you like

Origin www.cnblogs.com/mollnn/p/12398270.html