bzoj-1009-dp+kmp处理转移矩阵幂
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4723 Solved: 2940
[Submit][Status][Discuss]
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
HINT
Source
一个容易想到的转移方程是f[i][j]表示当前学号长度为i,在状态j时的方案个数,它可以推出的状态就是->f[i+1][k],下一步可以选择的数字[0,9],根据失配指针寻找应该转移到的状态k就好了,就是AC自动机,只不过是单链的为了方便用kmp处理。显然所有的f[i+1][]状态都来自于
f[i][],于是想到利用转移矩阵A,实现 (f[i][0],f[i][1],,,f[i][m])*A=(f[i+1][0],f[i+1][1],,,,f[i+1][m]),矩阵A[i][j]表示f[i+1][j]+=A[i][j]*f[i][j].
1 #include<iostream> 2 #include<cstring> 3 #include<queue> 4 #include<cstdio> 5 #include<stack> 6 #include<set> 7 #include<map> 8 #include<cmath> 9 #include<ctime> 10 #include<time.h> 11 #include<algorithm> 12 #include<bits/stdc++.h> 13 using namespace std; 14 #define mp make_pair 15 #define pb push_back 16 #define debug puts("debug") 17 #define LL long long 18 #define pii pair<int,int> 19 #define eps 1e-10 20 #define inf 0x3f3f3f3f 21 22 LL N,M,K; 23 int f[22]; 24 char s[22]; 25 struct matrix{ 26 LL len; 27 LL a[22][22]; 28 matrix(){ 29 memset(a,0,sizeof(a)); 30 } 31 matrix& operator*(matrix& tmp){ 32 matrix ans; 33 ans.len=len; 34 for(int i=0;i<=len;++i){ 35 for(int j=0;j<=len;++j){ 36 for(int k=0;k<=len;++k){ 37 ans.a[i][k]+=a[i][j]*tmp.a[j][k]; 38 ans.a[i][k]%=K; 39 } 40 } 41 } 42 return ans; 43 } 44 45 }A,I; 46 matrix qpow(matrix X,int n){ 47 matrix ans=I; 48 while(n){ 49 if(n&1) ans=ans*X; 50 X=X*X; 51 n>>=1; 52 } 53 return ans; 54 } 55 void init(){ 56 int i,j,k,len; 57 I.len=A.len=M; 58 for(i=0;i<=M;++i)I.a[i][i]=1; 59 len=strlen(s+1); 60 f[0]=0; 61 f[1]=0; 62 for(i=2;i<=len;++i){ 63 j=f[i-1]; 64 while(j&&s[j]!=s[i-1]) j=f[j]; 65 f[i]=j+1; 66 } 67 68 for(i=0;i<len;++i){ 69 for(j=0;j<10;++j){ 70 if(s[i+1]-'0'==j){ 71 A.a[i][i+1]++; 72 } 73 else{ 74 k=f[i+1]; 75 while(k&&s[k]-'0'!=j) k=f[k]; 76 A.a[i][k]++; 77 } 78 } 79 } 80 A.a[len-1][len]=0; 81 82 } 83 int main(){ 84 int i,j,k; 85 scanf("%lld%lld%lld",&N,&M,&K); 86 scanf("%s",s+1); 87 init(); 88 matrix ans=qpow(A,N); 89 LL res=0; 90 for(i=0;i<=ans.len;++i){ 91 res+=ans.a[0][i]; 92 res%=K; 93 } 94 cout<<res<<endl; 95 return 0; 96 }