Description
阿申准备报名参加GT考试,准考证号为N位数X1X2….Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2…Am(0<=Ai<=9)有M位,不出现是指X1X2…Xn中没有恰好一段等于A1A2…Am. A1和X1可以为0
Input
第一行输入N,M,K.接下来一行输入M位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6
Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.
Sample Input
4 3 100
111
Sample Output
81
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const int M=20+5;
int n,m,mod;
struct Mat{
int v[M][M];
void set(int x){
memset(v,0,sizeof v);
if (x==1)
for (int i=0;i<m;i++)
v[i][i]=1;
}
Mat operator * (Mat x){
Mat ans;
ans.set(0);
for (int i=0;i<m;i++)
for (int j=0;j<m;j++)
for (int k=0;k<m;k++){
ans.v[i][j]+=v[i][k]*x.v[k][j];
if (ans.v[i][j]>=mod)
ans.v[i][j]%=mod;
}
return ans;
}
}M1,My,Mans;
Mat Pow(int y){
if (y==0)
return M1;
Mat x=Pow(y/2);
x=x*x;
if (y&1)
x=x*My;
return x;
}
int p[M][12],next[M];
char ch[M];
int main(){
scanf("%d%d%d%s",&n,&m,&mod,&ch);
int k=0;
memset(next,0,sizeof next);
for (int i=1;i<m;i++){
while (k>0&&ch[i]!=ch[k])
k=next[k-1];
if (ch[i]==ch[k])
k++;
next[i]=k;
}
for (int j=0;j<=9;j++)
if (ch[0]==j+‘0‘)
p[0][j]=1;
else
p[0][j]=0;
for (int i=1;i<m;i++)
for (int j=0;j<=9;j++){
char chj=j+‘0‘;
int k=i;
while (k>0&&ch[k]!=chj)
k=next[k-1];
if (ch[k]==chj)
k++;
p[i][j]=k;
}
M1.set(1);
My.set(0);
for (int i=0;i<m;i++)
for (int j=0;j<=9;j++)
My.v[i][p[i][j]]++;
Mans=Pow(n);
int ans=0;
for (int i=0;i<m;i++)
ans=(ans+Mans.v[0][i])%mod;
printf("%d",ans);
return 0;
}