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位的数。 N<=10^9,M<=20,K<=1000
Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.
Sample Input
4 3 100
111
111
Sample Output
81
这道题是一个KMP+DP+矩阵快速幂,设dp[i][j]表示匹配到第i个数时匹配到第j个不吉利数字,r[j][k]表示dp[i][j]后添加一位数字可以转到状态k的次数,然后对r进行n次矩阵快速幂后统计第一行之和就是答案,下面是程序:
#include<stdio.h> #include<iostream> using namespace std; char a[25]; int n,m,mod,next[25],s[25][25],r[25][25]; void read(int &s){ s=0; char c=getchar(); while(c<'0'||c>'9'){ c=getchar(); } while(c>='0'&&c<='9'){ s*=10; s+=c-'0'; c=getchar(); } } void read(char *a){ char c=getchar(); int l=0; while(c<'0'||c>'9'){ c=getchar(); } while(c>='0'&&c<='9'){ a[l++]=c; c=getchar(); } a[l]='\0'; } void mul(int (*s)[25],int (*a)[25],int (*b)[25]){ int i,j,k,tp[25][25]; for(i=0;i<m;i++){ for(j=0;j<m;j++){ tp[i][j]=0; for(k=0;k<m;k++){ tp[i][j]+=a[i][k]*b[k][j]; tp[i][j]%=mod; } } } for(i=0;i<m;i++){ for(j=0;j<m;j++){ s[i][j]=tp[i][j]; } } } int main(){ read(n); read(m); read(mod); read(a+1); int i,j; for(i=2,j=0;i<=m;i++){ while(j>0&&a[j+1]!=a[i]){ j=next[j]; } if(a[j+1]==a[i]){ ++j; } next[i]=j; } for(i=0;i<m;i++){ for(j=0;j<=9;j++){ int t=i; while(t>0&&a[t+1]-'0'!=j){ t=next[t]; } if(a[t+1]-'0'==j){ t++; } if(t!=m){ r[i][t]++; r[i][t]%=mod; } } } s[0][0]=1; while(n){ if(n&1){ mul(s,s,r); } mul(r,r,r); n>>=1; } int ans=0; for(i=0;i<m;i++){ ans+=s[0][i]; ans%=mod; } printf("%d\n",ans); return 0; }