# [BZOJ1009]GT考试[矩阵快速幂+kmp]

$f_{i,j}$ 表示X串前 $i$ 位 匹配到A串第 $j$ 位的方案数，因为不能匹配到A串第 $m$ 位，所以答案是 $\sum_{i=0}^{m-1}f_{n,i}$

$f[i][j] = \sum_{k=0}^{m-1} f[i-1][k] * g[k][j]$

g[i][j] 是 从第 i 位匹配到第 j 位的方案数

$f_{i-1} \times G=f_i$

$f_0\times G^n = G^n$ 的第一行 所以就没有再写一遍乘法了

namespace QvvQ {
int n = in, m = in, mod = in, nxt[25];
char s[24];
struct Mod {
int a;
Mod(int _a) : a(_a) {}
Mod(ll _a) : a(_a % mod) {}
Mod() {}
int inv() {return Pow(a, mod - 2, mod);}
inline Mod &operator += (const int b) {a += b; if (a < 0) a += mod; else if (a >= mod) a -= mod; return *this;}
inline Mod &operator -= (const int b) {a -= b; if (a < 0) a += mod; else if (a >= mod) a -= mod; return *this;}
inline Mod &operator *= (const int b) {a = a * 1ll * b % mod; if (a < 0) a += mod; return *this;}
inline Mod &operator /= (const int b) {a = a * 1ll * Pow(b, mod - 2, mod) % mod; if (a < 0) a += mod; return *this;}
inline Mod &operator += (const Mod rhs) {return *this += rhs.a;}
inline Mod &operator -= (const Mod rhs) {return *this -= rhs.a;}
inline Mod &operator *= (const Mod rhs) {return *this *= rhs.a;}
inline Mod &operator /= (const Mod rhs) {return *this /= rhs.a;}
friend Mod inline operator + (Mod c, const Mod rhs) {return c += rhs.a;}
friend Mod inline operator - (Mod c, const Mod rhs) {return c -= rhs.a;}
friend Mod inline operator * (Mod c, const Mod rhs) {return c *= rhs.a;}
friend Mod inline operator / (Mod c, const Mod rhs) {return c /= rhs.a;}
inline Mod &operator = (const int x) {a = x; return *this;}
inline Mod &operator = (const ll x) {a = x % mod; return *this;}
inline Mod &operator = (const Mod rhs) {a = rhs.a; return *this;}
};
// f[i][j] = \sum_{k=0}^m-1 f[i-1][k] * g[k][j]
struct Matrix {
int n;
Mod a[23][21];
Matrix(int _n = 0) {n = _n; lo0(i, n) lo0(j, n) a[i][j] = 0;}
Matrix operator * (const Matrix &rhs) const {
Matrix res(n);
lo0(k, n)
lo0(i, n) {
if (!a[i][k].a) continue;
lo(j, 0, rhs.n) res.a[i][j] += a[i][k] * 1ll * rhs.a[k][j];
}
return res;
}
Matrix operator ^ (int x) const {
Matrix res(n), A; A.n = n;
lo0(i, n) res.a[i][i] = 1;
lo0(i, n) lo0(j, n) A.a[i][j] = a[i][j];
while (x) {
if (x & 1) res = res * A;
A = A * A;
x >>= 1;
}
return res;
}
} G(m);
void init() {
in, s + 1;
nxt[1] = 0;
for (int i = 2, j = 0; i <= m; ++i) {
while (j && s[j + 1] != s[i]) j = nxt[j];
j += s[j + 1] == s[i], nxt[i] = j;
}
lo0(i, m)
lo(cc, '0', '9') {
int j = i;
while (j && s[j + 1] != cc) j = nxt[j];
j += s[j + 1] == cc, G.a[i][j] += 1;
}
}

void solve() {
//其实初始的f_0应该是[1,0,0,0,0,0....] 即f_{0,0}=1
//f_n*G_n = G_n的第一行 所以就没有再写乘法了
G = G ^ n;
Mod ans = 0;

lo0(i, m) ans += G.a[0][i];
out, ans.a;
}

}

posted @ 2019-03-11 13:35  QvvQ  阅读(59)  评论(0编辑  收藏