zoukankan      html  css  js  c++  java
  • bzoj1009题解

    【解题思路】

      先KMP出fail数组,再用fail数组求出M[i][j],表示上一次匹配到第i位,这次可以遇到多少种不同的字符,使之转而匹配到第j位。

      设集合S=[1,m]∩N

      又设f[i][j]表示共读入了i个字符,当前匹配到了第j位时,有多少种情况。有转移方程f[i][j]=Σf[i-1][k]*M[k][j](k∈S),边界f[0][i]=[i=0](i∈S)。

      上述转移方程等价于行向量f[i]=f[i-1]*M,故f[n]=f[0]*Mn,又f[0]=[1,0,...,0],故f[n]=Mn。答案即为∑f[n][i](i∈S)。复杂度O(m2log2n)。

    【参考代码】

     1 #pragma GCC optimize(2)
     2 #include <cstdio>
     3 #include <cstring>
     4 #define REP(i,low,high) for(register int i=(low);i<=(high);++i)
     5 using namespace std;
     6  
     7 static int n,m,AwD; char jiry[25]; int fail[25]={0};
     8  
     9 struct matrix
    10 {
    11     int mat[25][25]; matrix() {memset(mat,0,sizeof mat);}
    12     matrix(const int&thr)
    13     {
    14         memset(mat,0,sizeof mat); REP(i,0,m-1) mat[i][i]=thr;
    15     }
    16     int&operator()(const int&x,const int&y) {return mat[x][y];}
    17     matrix&operator=(const matrix&thr)
    18     {
    19         return memcpy(mat,thr.mat,sizeof thr.mat),*this;
    20     }
    21     matrix&operator=(const int&thr)
    22     {
    23         memset(mat,0,sizeof mat); REP(i,0,m-1) mat[i][i]=thr; return *this;
    24     }
    25     matrix operator*(const matrix&thr)
    26     {
    27         matrix ret; REP(i,0,m-1) REP(j,0,m-1) REP(k,0,m-1)
    28         {
    29             if((ret.mat[i][j]+=mat[i][k]*thr.mat[k][j]%AwD)>=AwD)
    30             {
    31                 ret.mat[i][j]-=AwD;
    32             }
    33         }
    34         return ret;
    35     }
    36     matrix&operator*=(const matrix&thr)
    37     {
    38         matrix ret; REP(i,0,m-1) REP(j,0,m-1) REP(k,0,m-1)
    39         {
    40             if((ret.mat[i][j]+=mat[i][k]*thr.mat[k][j]%AwD)>=AwD)
    41             {
    42                 ret.mat[i][j]-=AwD;
    43             }
    44         }
    45         return memcpy(mat,ret.mat,sizeof ret.mat),*this;
    46     }
    47     matrix operator^(const int&thr)
    48     {
    49         matrix bas(*this),ret(1);
    50         for(register int i=thr;i;i>>=1,bas*=bas) if(i&1) ret*=bas;
    51         return ret;
    52     }
    53     matrix&operator^=(const int&thr)
    54     {
    55         matrix bas(*this),ret(1);
    56         for(register int i=thr;i;i>>=1,bas*=bas) if(i&1) ret*=bas;
    57         return memcpy(mat,ret.mat,sizeof ret.mat),*this;
    58     }
    59 }M;
    60  
    61 int main()
    62 {
    63     scanf("%d%d%d%s",&n,&m,&AwD,jiry+1),fail[1]=0;
    64     REP(i,2,m)
    65     {
    66         int idx=fail[i-1]; for(;idx&&jiry[idx+1]!=jiry[i];idx=fail[idx]);
    67         fail[i]=idx+(jiry[idx+1]==jiry[i]);
    68     }
    69     REP(i,0,m-1) REP(j,'0','9')
    70     {
    71         int idx=i; for(;idx&&jiry[idx+1]!=j;idx=fail[idx]);
    72         idx+=jiry[idx+1]==j; if(idx<m&&++M(idx,i)==AwD) M(idx,i)=0;
    73     }
    74     M^=n; int ans=0; REP(i,0,m-1) if((ans+=M(i,0))>=AwD) ans-=AwD;
    75     return printf("%d
    ",ans),0;
    76 }
    View Code
    We Secure, We Contain, We Protect.
  • 相关阅读:
    Windows下利用TortoiseSVN搭建本地SVN服务器
    我的Netty笔记
    Netty简单的HTTP服务器
    开启和关闭HBase的thrift进程
    java中重载和重写的区别
    java中形参个数可变的方法使用
    java中方法的参数传递机制
    Java内存分配全面浅析
    java中的类修饰符、成员变量修饰符、方法修饰符。
    js实现页面重定向
  • 原文地址:https://www.cnblogs.com/spactim/p/6426427.html
Copyright © 2011-2022 走看看