[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;
}