LGOJP3193 [HNOI2008] GT test

\ (f [i] [j ] \) represents the current to the second display \ (I \) bits, then the length of the current match \ (J \)

  • \(f[i][j]=\sum {f[i][k]*g[k][j]}\)

\ (g [i] [j ] \) shows a length \ (I \) matching length becomes \ (J \) the number of matching programs. This can be pre-kmp out: Enumeration currently match the length \ (i \) and the next character to put the current, jump \ (nxt \) look to match the length of each of \ (g [i] [ j] +1 \) can be. This is \ (O (10 \ times m
^ 2) \) then the matrix equation to optimize power quick click.
The total complexity is \ (O (10 \ times m ^ 2 + m ^ 3 \ log n) \)

/*
$f[i][j]$表示当前摆放到第$i$位,然后当前的匹配长度为$j$
* $f[i][j]=\sum {f[i][k]*g[k][j]}$
$g[i][j]$表示加一个字符将长度为$i$的匹配变成长度为$j$的匹配的方案数。这个可以kmp预处理出来。
*/
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 25;

inline void read(int &x) {
    x = 0; int f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar();
    }
    x *= f;
}

int n, m, mod, nxt[N];
char a[N];

struct mat {
    int c[21][21];
    mat() {memset(c, 0, sizeof(c));}
    mat operator * (mat &x) {
        mat ans;
        for(int i = 0; i < m; ++i) 
            for(int j = 0; j < m; ++j) 
                for(int k = 0; k < m; ++k)
                    (ans.c[i][j] += c[i][k] * x.c[k][j] % mod) %= mod;
        return ans;
    }
}A;

int main() {
#ifndef ONLINE_JUDGE
freopen("data.in","r",stdin);
#endif  
    read(n); read(m); read(mod);
    scanf("%s", a + 1);
    memset(nxt, 0, sizeof(nxt));
    for(int i = 2, j = 0; i <= m; ++i) {
        while(j && a[j + 1] != a[i]) j = nxt[j];
        if(a[j + 1] == a[i]) ++j;
        nxt[i] = j;
    }
    for(int i = 0; i < m; ++i) {
        for(int j = '0'; j <= '9'; ++j) {
            int tmp = i;
            while(tmp && a[tmp + 1] != j) tmp = nxt[tmp];
            if(a[tmp + 1] == j) ++tmp;
            if(tmp != m) ++A.c[i][tmp];
        }   
    }
    mat ans;
    ans.c[0][0] = 1;
    while(n) {
        if(n & 1) ans = ans * A;
        A = A * A; n >>= 1;
    }
    int Ans = 0;
    for(int i = 0; i < m; ++i) (Ans += ans.c[0][i]) %= mod;
    printf("%d\n", Ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/henry-1202/p/11824340.html