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 }
原文地址:https://www.cnblogs.com/proverbs/p/2945053.html