1009: [HNOI2008]GT考试
Submit: 4313 Solved: 2643
[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
1 #include<iostream> 2 #include<string> 3 #define M 25 4 using namespace std; 5 6 int n,m,d;string s; 7 int next[M]={0},a[M][M]={0}; 8 9 void Next(){ 10 for(int i=2;i<s.size();++i) 11 { 12 int j=i-1; 13 while(j!=0) 14 { 15 if(s[i]==s[next[j]+1]) break; 16 j=next[j]; 17 } 18 if(j==0) next[i]=0; 19 else next[i]=next[j]+1; 20 } 21 22 return ; 23 24 } 25 26 void Init(){ 27 for(int i=0;i<m;++i) 28 { 29 int j=i,sum=1; 30 a[i][j+1]=1; 31 bool p[10]={0}; 32 p[s[j+1]-'0']=1; 33 34 while(j!=0) 35 { 36 j=next[j]; 37 if(p[s[j+1]-'0']==0) 38 { 39 a[i][j+1]=1; 40 p[s[j+1]-'0']=1; 41 sum++; 42 } 43 } 44 a[i][0]=10-sum; 45 } 46 } 47 48 void Multiply(int re[][M],int x[][M],int y[][M]){ 49 for(int i=0;i<m;++i) 50 for(int j=0;j<m;++j) 51 for(int k=0;k<m;++k) 52 {re[i][j]+=x[i][k]*y[k][j];re[i][j]%=d;} 53 return ; 54 } 55 56 void Solve(int re[][M],int x[][M],int t){ 57 if(t==1) 58 { 59 for(int i=0;i<m;++i) 60 for(int j=0;j<m;++j) 61 re[i][j]=x[i][j]; 62 return ; 63 } 64 65 int y[M][M]={0},z[M][M]={0}; 66 Solve(y,x,t/2); 67 68 69 70 Multiply(z,y,y); 71 72 if(t%2==1) 73 Multiply(re,z,x); 74 else 75 { 76 for(int i=0;i<m;++i) 77 for(int j=0;j<m;++j) 78 re[i][j]=z[i][j]; 79 80 } 81 return ; 82 } 83 84 int main() 85 { 86 cin>>n>>m>>d; 87 cin>>s; 88 s=" "+s; 89 90 Next(); 91 92 Init(); 93 94 int an[M]={0},ans[M]={0}; 95 an[0]=9; 96 an[1]=1; 97 98 int b[M][M]={0}; 99 Solve(b,a,n-1); 100 101 102 103 for(int i=0;i<m;++i) 104 for(int j=0;j<m;++j) 105 {ans[i]+=an[j]*b[j][i];ans[i]%=d;} 106 107 108 109 for(int i=1;i<m;++i) 110 {ans[0]+=ans[i];ans[0]%=d;} 111 112 113 cout<<ans[0]<<endl; 114 115 // system("pause"); 116 117 }