BZOJ1009: [HNOI2008]GT考试
Dp·KMP·矩阵优化
题解:
不想自己写题解系列。
http://blog.csdn.net/loi_dqs/article/details/50897662
Code:
#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
const ll N = 25;
ll n,m,mod,fail[N]; char s[N];
struct Matrix{
ll d[N][N]; ll x,y;
Matrix(ll _x,ll _y,ll op=0){
x=_x; y=_y;
for(ll i=0;i<x;i++) for(ll j=0;j<y;j++)
if(i==j) d[i][j]=op; else d[i][j]=0;
}
ll* operator [] (ll x){ return d[x]; }
void debug(){
// puts("debug:");
// D(x); D(y); E;
// for(ll i=0;i<x;i++) for(ll j=0;j<y;j++)
// printf("%lld%c",d[i][j],j==y-1?'\n':' ');
}
};
Matrix operator * (Matrix &a, Matrix &b){
Matrix c(a.x,b.y);
for(ll i=0;i<a.x;i++) for(ll j=0;j<a.y;j++) for(ll k=0;k<b.y;k++)
c[i][k]=(c[i][k]+a[i][j]*b[j][k]%mod)%mod;
return c;
}
Matrix pow(Matrix a,ll k){
Matrix res(a.x,a.y,1);
while(k){
if(k&1) res=res*a;
a=a*a; k>>=1;
}
return res;
}
void getfail(Matrix &a){
fail[0]=0; fail[1]=0;
for(ll i=1;i<m;i++){
ll j=fail[i];
while(j && s[i]!=s[j]) j=fail[j];
fail[i+1]= s[i]==s[j] ? j+1 : 0;
}
for(ll i=0;i<m;i++){
for(ll j=0;j<=9;j++){
ll p=i;
while(p && s[p]!=j+'0') p=fail[p];
if(s[p]==j+'0') p++;
if(p<m) a[i][p]++;
}
}
}
int main(){
freopen("a.in","r",stdin);
scanf("%lld%lld%lld%s",&n,&m,&mod,s);
Matrix a(m,m); getfail(a); a.debug();
a=pow(a,n); a.debug();
Matrix f(1,m); f[0][0]=1;
f=f*a; f.debug();
ll ans=0;
for(ll i=0;i<m;i++) ans=(ans+f[0][i])%mod;
printf("%lld\n",ans);
}