BZOJ 1009 [HNOI2008]GT考试 矩阵乘法+DP
题解:
dp[i][j]表示长度为i,匹配了j个的方案数,压缩成矩阵,转移即可。
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <algorithm> 6 7 #define SIZE 21 8 9 using namespace std; 10 11 struct MT 12 { 13 int x,y; 14 int mt[SIZE][SIZE]; 15 void prt() 16 { 17 for(int i=0;i<=x;i++){ 18 for(int j=0;j<=y;j++) 19 printf("%d ",mt[i][j]);puts("");} 20 } 21 }ans,zy; 22 23 int n,m,mod; 24 char a[SIZE],b[SIZE],c[SIZE]; 25 int len,lenc; 26 27 inline MT operator *(MT a,MT b) 28 { 29 MT c; memset(c.mt,0,sizeof c.mt); 30 c.x=a.x; c.y=b.y; 31 for(int i=0;i<=c.x;i++) 32 for(int j=0;j<=c.y;j++) 33 { 34 for(int k=0;k<=a.y;k++) 35 c.mt[i][j]+=a.mt[i][k]*b.mt[k][j]; 36 c.mt[i][j]%=mod; 37 } 38 return c; 39 } 40 41 inline void read() 42 { 43 scanf("%d%d%d",&n,&m,&mod); 44 scanf("%s",a+1); 45 } 46 47 inline void getstring(int x,int y) 48 { 49 len=0; 50 for(int i=1;i<=x;i++) b[++len]=a[i]; 51 b[++len]=y; 52 } 53 54 inline void getsuf(int x) 55 { 56 lenc=0; 57 for(int i=len-x+1;i<=len;i++) c[++lenc]=b[i]; 58 } 59 60 inline bool check() 61 { 62 for(int i=1;i<=lenc;i++) 63 if(a[i]!=c[i]) return false; 64 return true; 65 } 66 67 inline void prep() 68 { 69 for(int i=0;i<m;i++) 70 for(int j=0;j<=9;j++) 71 { 72 getstring(i,j+'0'); 73 for(int k=len;k>=0;k--) 74 { 75 if(k==m) 76 { 77 getsuf(k); 78 if(check()) break; 79 else continue; 80 } 81 getsuf(k); 82 if(check()) {zy.mt[k][i]++;break;}//转移反过来写!! 83 } 84 } 85 zy.x=zy.y=m-1; 86 ans.x=m-1; ans.y=0; 87 ans.mt[0][0]=1; 88 } 89 90 inline void go() 91 { 92 prep(); 93 while(n) 94 { 95 if(n&1) ans=zy*ans; 96 zy=zy*zy; 97 n>>=1; 98 } 99 int res=0; 100 for(int i=0;i<m;i++) res+=ans.mt[i][0]; 101 cout<<res%mod<<endl; 102 } 103 104 int main() 105 { 106 read(),go(); 107 return 0; 108 }
没有人能阻止我前进的步伐,除了我自己!