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
111
Sample Output
81
是个DP,然后我开始想用总个数-不可行个数求,yy了半个小时,不行
题解说这个题f[i][j]=f[i][k]*a[k][j]
a[k][j] 表示从f[i-1][k]转移到f[i][j]的方案数
用kmp构造出初始矩阵表示如果a[i][j]==1则说明i的fail指针指向j,矩阵快速幂就好了
1 #include<cstdio> 2 int n,m,mod; 3 int fail[25]; 4 char s[25]; 5 int a[25][25],b[25][25]; 6 void mul(int a[25][25],int b[25][25],int ans[25][25]) 7 { 8 int tmp[25][25]; 9 for(int i=0;i<m;i++) 10 for(int j=0;j<m;j++) 11 { 12 tmp[i][j]=0; 13 for(int k=0;k<m;k++) 14 tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod; 15 } 16 for(int i=0;i<m;i++) 17 for(int j=0;j<m;j++) 18 ans[i][j]=tmp[i][j]; 19 } 20 void pre(){ 21 for(int i=0;i<m;i++) 22 for(int j=0;j<=9;j++){ 23 int t=i; 24 while(t&&s[t+1]-'0'!=j) t=fail[t]; 25 if(s[t+1]-'0'==j) t++; 26 b[i][t]++; 27 } 28 } 29 30 void kmp(){ 31 int j=0; 32 for(int i=2;i<=m;i++){ 33 while(j>0&&s[j+1]!=s[i]) j=fail[j]; 34 if(s[j+1]==s[i])j++; 35 fail[i]=j; 36 } 37 } 38 39 int main(){ 40 scanf("%d%d%d%s",&n,&m,&mod,s+1); 41 kmp(); 42 pre(); 43 for(int i=0;i<m;i++) a[i][i]=1; 44 while(n) 45 { 46 if(n&1)mul(a,b,a); 47 mul(b,b,b); 48 n>>=1; 49 } 50 int sum=0; 51 for(int i=0;i<m;i++) sum=(a[0][i]+sum)%mod; 52 printf("%d",sum); 53 } 54