BZOJ 1009: [HNOI2008]GT考试

妈耶之前因为不熟KMP一直觉得这题好难,现在发现当年真是naive

首先我们容易设出一个DP,\(f_{i,j}\)表示准考证上前\(i\)位的长度为\(j\)的后缀与不吉利的数字的长度为\(j\)的前缀匹配的方案数

那么显然\(ans=\sum_{i=0}^{m-1} f_{n,i}\),考虑\(f\)如何转移

假设现在做到\(i\)的位置,\(f_{i-1}\)显然是已知的,那么就考虑多加入一个数字会带来什么影响

由于这里DP的特性,我们设一个\(g_{i,j}\)表示在不吉利的数字串上匹配时,加入一个数字,能加入多少种,使得长度为\(i\)的匹配变成长度为\(j\)的匹配

画画图就会发现原来和准考证号匹配的是前缀,而这里加入的是后缀,因此就是个最大前缀后缀匹配的问题,这就是一个裸KMP啊

然后我们轻易地求出了\(g\),然后发现这个转移就是个矩乘的形式,因此直接做就好了

#include
#include
#define RI register int
#define Ms(f,x) memset(f,x,sizeof(f))
using namespace std;
const int R=25;
struct Matrix
{
    int n,m,a[R][R];
    Matrix(int N=0,int M=0) { n=N; m=M; Ms(a,0); }
    inline void Cir_init(void)
    {
        for (RI i=0;i=mod) x-=mod;
}
inline Matrix operator *(Matrix A,Matrix B)
{
    Matrix C(A.n,B.m); for (RI i=0;i>=1,A=A*A) if (p&1) T=T*A; return T;
}
int main()
{
    RI i,j; scanf("%d%d%d%s",&n,&m,&mod,s+1); Matrix A(m,m);
    for (KMP(),i=0;i

你可能感兴趣的:(BZOJ 1009: [HNOI2008]GT考试)