luogu P3193 [HNOI2008]GT考试
题面传送门
\(n\)这么大肯定只能矩乘(暴论
但是不能出现这个串的限制很难搞,考虑设\(dp_{i,j}\)表示第\(i\)位然后匹配到答案第\(j\)位。
然后如果预处理出kmp就可以\(O(10nm)\)搞了。
把这个递推改成矩乘就可以\(O(m^3logn)\)轻松跑过。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define lb long db
#define N 20
#define W (1<<31)-1
#define mod 998244353
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Pc(x) putchar(x)
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,p,now,net[N+5],ToT;char S[N+5];
struct matrix{
int A[N+5][N+5];matrix(){Me(A,0);}
matrix operator *(matrix &B)const{
matrix C;re int i,j,h;for(h=0;h<=m;h++){
for(i=0;i<=m;i++)for(j=0;j<=m;j++) C.A[i][j]=(C.A[i][j]+A[i][h]*B.A[h][j])%p;
}return C;
}
}Ans,Bas;
int main(){
//freopen("1.in","r",stdin);
re int i,j;scanf("%d%d%d",&n,&m,&p);scanf("%s",S+1);for(i=1;i<=m;i++) S[i]-='0';for(i=1;i<=m;i++){net[i]=net[i-1];while(net[i]&&S[net[i]+1]^S[i])net[i]=net[net[i]];net[i]+=(i^1&&S[net[i]+1]==S[i]);}
for(i=0;i<m;i++){
for(j=0;j<=9;j++){
now=i;while(now&&S[now+1]^j) now=net[now];now+=(S[now+1]==j);Bas.A[i][now]++;
}
}Ans.A[0][0]=1;while(n)n&1&&(Ans=Ans*Bas,0),n>>=1,Bas=Bas*Bas;for(i=0;i<m;i++) ToT+=Ans.A[0][i];printf("%d\n",ToT%p);
}