HNOI2008 GT考试 (BZOJ1009,kmp+dp)

TP

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

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
",ans);
55 }
56 
57 int main(){
58     Pre();
59     Solve();
60     return 0;
61 }
原文地址:https://www.cnblogs.com/zjdx1998/p/3959915.html