zoukankan      html  css  js  c++  java
  • bzoj1009: [HNOI2008]GT考试(kmp+矩阵乘法)

    1009: [HNOI2008]GT考试

    题目:传送门 

    题解:

       看这第一眼是不是瞬间想起组合数学???

       没错...这样想你就GG了!

       其实这是一道稍有隐藏的矩阵乘法,好题!

       首先我们可以简化一下题意:给出一个串,要求这个串不包含另一个串的方案个数

       这不是kmp吗?!(直接暴力肯定炸)

       我们可以再往DP的方面想

       f[i][j]表示长度为i的母串的后缀与子串匹配j个长度的方案数

       那么ans=Sigma(f[n][0]~f[n][m-1])

       那么我们再定义一个c[i][j]表示在子串长度为i的前缀后面加上一个数,令该前缀加上这个数所组成的新字符串与给出子串从头开始所能匹配的长度为j的方案数

       那么f[i+1][k]=f[i][j]*c[j][k]

       但是还是会炸啊!!!!!!!

       这时候怎么就想不到矩乘加速呢?!

       c数组不变,而且每次f都要乘一次,很明显可以用矩阵乘法。。。

       所以用kmp预处理矩阵就ok,但是c[i][m]不能继承,所以只能从w[i][0]继承,矩乘时就枚举0~m-1

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 struct matrix
     8 {
     9     int m[25][25];
    10     matrix(){memset(m,0,sizeof(m));}
    11 }ans;
    12 char st[25];
    13 int p[25];
    14 int n,m,mod;
    15 matrix multi(matrix a,matrix b,int n,int m,int p)//[n,m]*[m,p];
    16 {
    17     matrix c;
    18     for(int i=0;i<n;i++)
    19         for(int j=0;j<p;j++)
    20             for(int k=0;k<m;k++)
    21                 c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
    22     return c;
    23 }
    24 matrix p_m(matrix a,int b)
    25 {
    26     matrix sum;
    27     for(int i=0;i<m;i++)sum.m[i][i]=1;
    28     while(b)
    29     {
    30         if(b%2==1)sum=multi(sum,a,m,m,m);
    31         a=multi(a,a,m,m,m);b/=2;
    32     }
    33     return sum;
    34 }
    35 void kmp()
    36 {
    37     p[1]=0;int j;
    38     for(int i=2;i<=m;i++)
    39     {
    40         j=p[i-1];
    41         while(j && st[i]!=st[j+1])j=p[j];
    42         if(st[i]==st[j+1])j++;
    43         p[i]=j;
    44     }
    45     for(int i=0;i<m;i++)
    46     {
    47         for(int y=0;y<=9;y++)
    48         {
    49             j=i;
    50             while(j && st[j+1]-'0'!=y)j=p[j];
    51             if(st[j+1]-'0'==y)j++;
    52             ans.m[j][i]=(ans.m[j][i]+1)%mod;
    53         }
    54     }
    55 }
    56 int main()
    57 {
    58     scanf("%d%d%d",&n,&m,&mod);
    59     scanf("%s",st+1);
    60     kmp();
    61     ans=p_m(ans,n);
    62     int sum=0;
    63     for(int i=0;i<m;i++)sum=(sum+ans.m[i][0])%mod;
    64     printf("%d
    ",sum%mod);
    65     return 0;
    66 }
    67 
  • 相关阅读:
    Qt为啥从4.8直接就跳到5.3了呢?这不科学吧
    一段程序的人生 第10章: server
    项目记录23--unity-tolua框架MediatorManager
    Raft 为什么是更易理解的分布式一致性算法
    Caused by: java.lang.UnsatisfiedLinkError: Couldn&#39;t load BaiduMapVOS_v2_1_3: findLibrary returned nu
    Apache OFBIZ高速上手(二)--MVC框架
    Eclipse 导入逆向工程
    mysql 报错从 新安装
    maven项目创建4
    maven报错
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8425151.html
Copyright © 2011-2022 走看看