1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4065 Solved: 2475
[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
很久以前就开始写了,写了很久,到现在才懵懵懂懂的搞好
下面是借用的题解,事实证明我的KMP还需加强!
http://blog.csdn.net/loi_dqs/article/details/50897662
1 #include "bits/stdc++.h" 2 using namespace std; 3 typedef long long LL; 4 const int MAX=50; 5 int n,m,mod; 6 char s[MAX]; 7 int next[MAX]; 8 struct Mat{ 9 int x,y; 10 int mat[MAX][MAX]; 11 Mat(){x=y=0;memset(mat,0,sizeof(mat));} 12 void init(int xx,int yy){ 13 int i,j; 14 x=xx;y=yy; 15 for (i=1;i<=min(x,y);i++) 16 mat[i][i]=1; 17 } 18 Mat operator * (const Mat &tt) { 19 int i,j,k; 20 Mat an; 21 an.x=x,an.y=tt.y; 22 for (k=1;k<=y;k++){ 23 for (i=1;i<=an.x;i++){ 24 if (mat[i][k]){ 25 for (j=1;j<=an.y;j++){ 26 an.mat[i][j]=(an.mat[i][j]+mat[i][k]*tt.mat[k][j])%mod; 27 } 28 } 29 } 30 } 31 return an; 32 } 33 }cc; 34 Mat ksm(Mat tt,int x){ 35 Mat an;an.init(tt.x,tt.y); 36 while (x){ 37 if (x%2) an=tt*an; 38 tt=tt*tt; 39 x>>=1; 40 } 41 return an; 42 } 43 void get_next(){ 44 int i,j; 45 j=0;next[0]=0; 46 for (i=1;i<m;i++){ 47 while (j && s[i]!=s[j]) j=next[j]; 48 next[i+1]=(s[i]==s[j]?++j:0); 49 } 50 } 51 int main(){ 52 freopen ("gt.in","r",stdin); 53 freopen ("gt.out","w",stdout); 54 int i,j,ans=0; 55 scanf("%d%d%d ",&n,&m,&mod); 56 gets(s);get_next(); 57 cc.x=cc.y=m; 58 for (i=1;i<=m;i++){ 59 for (j=0;j<=9;j++){ 60 int zt=i-1; 61 while (zt && j!=(s[zt]-'0')) zt=next[zt]; 62 if (j==(s[zt]-'0')) zt++; 63 if (zt!=m){ 64 cc.mat[zt+1][i]=(cc.mat[zt+1][i]+1)%mod; 65 } 66 } 67 } 68 cc=ksm(cc,n); 69 for (i=1;i<=m;i++){ 70 ans=(ans+cc.mat[i][1])%mod; 71 } 72 printf("%d ",ans); 73 return 0; 74 }