HNOI2008 GT考试 (BZOJ1009,kmp+dp)
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MB
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
。。做了这题才发现我kmp没学好。。很水的dp。。没什么好说的。。唉。。T_T..
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define For(i,n) for(int i=1;i<=n;i++) 8 #define Rep(i,l,r) for(int i=l;i<=r;i++) 9 10 struct Matrix{ 11 int A[25][25]; 12 Matrix(){memset(A,0,sizeof(A));} 13 }Unit,Ans; 14 15 char st[30]; 16 int n,m,K,next[30],ans; 17 18 Matrix operator * (Matrix A,Matrix B){ 19 Matrix C; 20 Rep(i,0,m-1) 21 Rep(j,0,m-1) 22 Rep(k,0,m-1) 23 C.A[i][j] = (C.A[i][j] + A.A[i][k]*B.A[k][j])%K; 24 return C; 25 } 26 27 void Pre(){ 28 scanf("%d%d%d",&n,&m,&K); 29 scanf("%s",&st); 30 next[0]=next[1]=0; 31 For(i,m){ 32 int j=next[i]; 33 while(j&&st[i]!=st[j]) j=next[j]; 34 if(st[i]==st[j]) next[i+1]=j+1; 35 else next[i+1]=0; 36 } 37 Rep(i,0,m-1) 38 Rep(k,0,9){ 39 int j=i; 40 while(j&&st[j]!=k+'0') j=next[j]; 41 if(k+'0'==st[j]) Unit.A[i][j+1]++; 42 else Unit.A[i][0]++; 43 } 44 } 45 46 void Solve(){ 47 Rep(i,0,m-1) Ans.A[i][i]=1; 48 while(n){ 49 if(n&1) Ans=Ans*Unit; 50 Unit=Unit*Unit; 51 n>>=1; 52 } 53 Rep(i,0,m-1) ans=(Ans.A[0][i]+ans)%K; 54 printf("%d\n",ans); 55 } 56 57 int main(){ 58 Pre(); 59 Solve(); 60 return 0; 61 }