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 }

 

 

你可能感兴趣的:(2008)