zoukankan      html  css  js  c++  java
  • luogu P3193 [HNOI2008]GT考试

    传送门

    单串匹配显然用(kmp)

    一个暴力的dp是设(f_{i,j}),表示前(i)位,正在匹配给定串第(j)位的方案,转移就枚举下一位放什么,然后使用(kmp)看会匹配到给定串的哪位

    但是(n)非常大,注意到(f_{i,j}->f_{i+1,k})这样的转移可以抽象为一条从(j)(k)的边,并且(m)很小,于是可以用匹配的关系构建出邻接矩阵,然后矩乘救星了

    不会矩乘优化dp的话可以做下这道题

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    #define eps (1e-7)
    
    using namespace std;
    const int N=22;
    il LL rd()
    {
      re LL x=0,w=1;re char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    int mod;
    struct martix
    {
      int n,m;
      int a[N][N];
      martix(){}
      il void init()
      {
        for(int i=0;i<n;i++) a[i][i]=1;
      }
      martix(int n,int m):n(n),m(m)
      {
        for(int i=0;i<n;i++)
          for(int j=0;j<m;j++)
        a[i][j]=0;
      }
      martix operator * (const martix &b) const
      {
        martix a=*this,an(a.n,b.m);
        for(int i=0;i<a.n;i++)
          for(int j=0;j<a.m;j++)
        for(int k=0;k<b.m;k++)
          an.a[i][j]=(an.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
        return an;
      }
      martix operator ^ (const LL &bb) const
      {
        martix a=*this,an(a.n,a.m);
        an.init();
        LL b=bb;
        while(b)
          {
        if(b&1) an=an*a;
        a=a*a;
        b>>=1;
          }
        return an;
      }
    };
    char cc[N];
    int nxt[N];
    int n,m;
    
    int main()
    {
      n=rd(),m=rd(),mod=rd();
      martix a(m,m),b(m,m);
      scanf("%s",cc);
      for(int i=1,k=0;i<m;i++)
        {
          while(k&&cc[i]!=cc[k]) k=nxt[k];
          nxt[i+1]=(cc[i]==cc[k])?++k:0;
        }
      for(int i=0;i<m;i++)
        {
          for(int j=0;j<=9;j++)
            {
              int k=i;
              while(k&&cc[k]!=j+'0') k=nxt[k];
              k+=(cc[k]==j+'0');
              ++b.a[i][k];
            }
        }
      a.a[0][0]=1;
      a=a*(b^n);
      int ans=0;
      for(int i=0;i<m;i++) ans=(ans+a.a[0][i])%mod;
      printf("%d
    ",ans);
      return 0;
    }
    
    
  • 相关阅读:
    安装设置Android Studio Win7安装
    执行对象cocos2dx 2.x action动作整理集合
    查询生成三大框架整合 提示 不能进行查询错误
    一些链接
    成员函数指针与高性能的C++委托
    举例说明Linux不同网段访问的设置办法
    ubuntu 服务管理
    Ubuntu之开机检测硬盘
    Ubuntu 10.04开启字符模式并设置静态IP
    Ubuntu终端ssh连接服务器慢的解决方法
  • 原文地址:https://www.cnblogs.com/smyjr/p/9739348.html
Copyright © 2011-2022 走看看