• 【bzoj1009】: [HNOI2008]GT考试 字符串-kmp-矩阵乘法-DP


    【bzoj1009】: [HNOI2008]GT考试

    先用kmp写个暴力

     1 /* http://www.cnblogs.com/karl07/ */
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <algorithm>
     7 using namespace std;
     8 char s[25];
     9 int n,m,p,fail[25],f[1000][25];
    10 
    11 void kmp(){
    12     fail[1]=0;
    13     for (int i=2;i<=m;i++){
    14         fail[i]=fail[i-1];
    15         if (s[fail[i-1]]==s[i-1]) fail[i-1]=fail[fail[i-1]];
    16         while (s[fail[i]]!=s[i-1] && fail[i]) fail[i]=fail[fail[i]];
    17         fail[i]++;
    18     }
    19 }
    20 
    21 int main(){
    22     scanf("%d%d%d",&n,&m,&p);
    23     scanf("%s",s+1);
    24     kmp();
    25     f[0][0]=1;
    26     for (int i=1;i<=n;i++){
    27         for (int j=0;j<m;j++){
    28             for (int k='0',now=j+1;k<='9';k++,now=j+1){
    29                 while (k!=s[now] && now) now=fail[now];
    30                 f[i][now]=(f[i][now]+f[i-1][j])%p;
    31             }
    32         }
    33     }
    34     int ans=0;
    35     for (int i=0;i<m;i++){
    36         ans=(ans+f[n][i])%p;
    37     }
    38     printf("%d
    ",ans);
    39     return 0;
    40 }
    暴力

    然后对着转移方程yy一下矩阵就好辣

     1 /* http://www.cnblogs.com/karl07/ */
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <algorithm>
     7 using namespace std;
     8 char s[25];
     9 int n,m,p,fail[25];
    10 struct MAT{
    11     int m[25][25];
    12     int x,y;
    13 }m1,m2;
    14 
    15 MAT operator * (const MAT &a,const MAT &b){
    16     MAT c;
    17     c.x=b.x,c.y=a.y;
    18     for (int i=1;i<=c.x;i++){
    19         for (int j=1;j<=c.y;j++){
    20             c.m[i][j]=0;
    21             for (int k=1;k<=b.y;k++){
    22                 c.m[i][j]=(c.m[i][j]+a.m[k][j]*b.m[i][k])%p;
    23             }
    24         }
    25     } 
    26     return c;
    27 }
    28 
    29 int sum(MAT a){
    30     int ans=0;
    31     for (int i=1;i<=a.x;i++){
    32         for (int j=1;j<=a.y;j++){
    33             ans=(ans+a.m[i][j])%p;
    34         }
    35     }
    36     return ans;
    37 }
    38 
    39 void kmp(){
    40     fail[1]=0;
    41     for (int i=2;i<=m;i++){
    42         fail[i]=fail[i-1];
    43         if (s[fail[i-1]]==s[i-1]) fail[i-1]=fail[fail[i-1]];
    44         while (s[fail[i]]!=s[i-1] && fail[i]) fail[i]=fail[fail[i]];
    45         fail[i]++;
    46     }
    47 }
    48 
    49 MAT qpow(int x){
    50     for (;x;x=(x>>1),m2=m2*m2) if (x&1) m1=m1*m2;
    51     return m1;
    52 }
    53 
    54 int main(){
    55     scanf("%d%d%d",&n,&m,&p);
    56     scanf("%s",s+1);
    57     kmp();
    58     m1.x=m;m1.y=1;m1.m[1][1]=1;
    59     m2.x=m2.y=m;
    60     for (int i=2;i<=m;i++) m1.m[i][1]=0;
    61     for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) m2.m[i][j]=0;
    62     for (int j=0;j<m;j++){
    63         for (int k='0',now=j+1;k<='9';k++,now=j+1){
    64             while (k!=s[now] && now)now=fail[now]; 
    65             m2.m[now+1][j+1]++;
    66         }
    67     }
    68     printf("%d
    ",sum(qpow(n)));
    69     return 0;
    70 }
    正解

     为什么感觉自己的kmp写的好奇怪。。

  • 相关阅读:
    05-java学习-循环结构
    04-java学习-选择结构
    03-java学习-基本数据类型-运算符-键盘接收用户输入
    A02-java学习-classpath配置-标识符-java变量类型
    A01-java学习环境准备
    20190215面试-C#操作外设-多线程-shocket
    装饰者模式
    状态模式
    DllImport学习
    网络编程(一)----基础知识、数据流套接字
  • 原文地址:https://www.cnblogs.com/karl07/p/6658083.html
Copyright © 2020-2023  润新知