[HNOI2008]GT考试

题解:

很水的一题吧。。

显然是kmp+dp

f[i][j]表示有i个字符,匹配到了j上

然后o(n)都过不来了那显然是要用矩阵优化的

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
char c[30];
ll f[30],mo1,n,m,k;
void get_fail(char *c,ll *f)
{
  ll m=strlen(c);
  for (ll i=1;i<m;i++)
  {
     ll j=f[i];
     while (j&&c[i]!=c[j]) j=f[j];
     f[i+1]=c[i]==c[j]?j+1:0;
  }
}
ll find(ll x,char cc,char *c,ll *f)
{
   while (x&&cc!=c[x]) x=f[x];
   if (cc==c[x]) x++;
   return x;
}
struct re{
  ll jz[30][30];
}a;
re XX(re x,re y)
{
  re tmp;
  memset(tmp.jz,0,sizeof(tmp.jz));
  for (ll i=1;i<=k;i++)
    for (ll j=1;j<=k;j++)
      for (ll l=1;l<=k;l++)
        tmp.jz[i][l]+=x.jz[i][j]*y.jz[j][l],
        tmp.jz[i][l]%=mo1;
  return (tmp);
}
re fastpow(ll x)
{
  if (x==1) return(a);
  re b=fastpow(x/2);
  b=XX(b,b);
  if (x%2==1) b=XX(b,a);
  return(b);
}
int main()
{
    freopen("noip.in","r",stdin);
    freopen("noip.out","w",stdout);
    cin>>n>>k>>mo1;
    cin>>c;
    get_fail(c,f);
    for (ll i=0;i<k;i++)
      for (ll j=0;j<=9;j++)
      {
        char cc='0'+j;
        ll tmp=find(i,cc,c,f);
        if (tmp!=k)
          a.jz[tmp+1][i+1]++;
        a.jz[tmp+1][i+1]%=mo1;
      }
    re dd;
    dd=fastpow(n); ll ans=0;
    for (ll i=1;i<=k;i++)
      ans+=dd.jz[i][1],ans%=mo1;
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/yinwuxiao/p/8570310.html