bzoj-1009-dp+kmp处理转移矩阵幂

1009: [HNOI2008]GT考试

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 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

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 }

 

posted @ 2018-05-14 09:19  *zzq  阅读(203)  评论(0编辑  收藏  举报