1. 程式人生 > >bzoj-1009-dp+kmp處理轉移矩陣冪

bzoj-1009-dp+kmp處理轉移矩陣冪

puts space cti AR data ems 方案 amp href

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 }

bzoj-1009-dp+kmp處理轉移矩陣冪