bzoj1009: [HNOI2008]GT考试

题解传送门http://www.cnblogs.com/Tunix/p/4412201.html

 

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>

using namespace std;

void setIO(const string& s) {
    freopen((s + ".in").c_str(), "r", stdin);
    freopen((s + ".out").c_str(), "w", stdout);
}
template<typename Q> Q read(Q& x) {
    static char c, f;
    for(f = 0; c = getchar(), !isdigit(c); ) if(c == '-') f = 1;
    for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
    if(f) x = -x;
    return x;
}
template<typename Q> Q read() {
    static Q x; read(x); return x;
}

const int N = 20 + 5;

int n, m, p;

template<typename Q> void addit(Q& x, const Q& y) {
    if((x += y) >= p) x -= p;
}

struct Matrix {
    int da[N][N];
    
    void clear() {
        memset(da, 0, sizeof da);
    }
    
    Matrix operator * (const Matrix& b) const {
        static Matrix c;
        c.clear();
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < m; j++){
                for(int k = 0; k < m; k++){
                    addit(c.da[i][j], da[i][k] * b.da[k][j] % p);
                }
            }
        }
        return c;
    }
}A, B;

char s[N];
int fail[N];

void kmp() {
    for(int j = 0, i = 2; i <= m; i++) {
        while(j && s[i] != s[j+1]) j = fail[j];
        if(s[i] == s[j+1]) j++;
        fail[i] = j;
    }
}

void getMatrixB() {
    for(int i = 0; i < m; i++) {
        for(int j = 0; j <= 9; j++) {
            int k = i;
            while(k && s[k+1] != j + '0') k = fail[k];
            if(s[k+1] == j + '0') ++k; 
            ++B.da[i][k];
        }
    }
}

Matrix qpow(Matrix a, int b) {
    Matrix c = a;
    for(b--; ; a = a * a) {
        if(b & 1) c = c * a;
        if(!(b >>= 1)) return c;
    }
}

int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    
    scanf("%d%d%d", &n, &m, &p);
    scanf("%s", s + 1);
    
    kmp();
    getMatrixB();
    A.da[0][0] = 1;
    B = qpow(B, n);
    A = A * B;
    int res = 0;
    for(int i = 0; i < m; i++) {
        addit(res, B.da[0][i]);
    }
    printf("%d\n", res);
    
    return 0;
}
View Code

 

posted @ 2015-12-21 20:31  Showson  阅读(152)  评论(0编辑  收藏  举报