您的位置:首页 > 其它

BZOJ 1009 [HNOI2008]GT考试 矩阵乘法+DP

2013-03-05 21:00 381 查看
题解:

dp[i][j]表示长度为i,匹配了j个的方案数,压缩成矩阵,转移即可。

View Code

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>

#define SIZE 21

using namespace std;

struct MT
{
int x,y;
int mt[SIZE][SIZE];
void prt()
{
for(int i=0;i<=x;i++){
for(int j=0;j<=y;j++)
printf("%d  ",mt[i][j]);puts("");}
}
}ans,zy;

int n,m,mod;
char a[SIZE],b[SIZE],c[SIZE];
int len,lenc;

inline MT operator *(MT a,MT b)
{
MT c; memset(c.mt,0,sizeof c.mt);
c.x=a.x; c.y=b.y;
for(int i=0;i<=c.x;i++)
for(int j=0;j<=c.y;j++)
{
for(int k=0;k<=a.y;k++)
c.mt[i][j]+=a.mt[i][k]*b.mt[k][j];
c.mt[i][j]%=mod;
}
return c;
}

inline void read()
{
scanf("%d%d%d",&n,&m,&mod);
scanf("%s",a+1);
}

inline void getstring(int x,int y)
{
len=0;
for(int i=1;i<=x;i++) b[++len]=a[i];
b[++len]=y;
}

inline void getsuf(int x)
{
lenc=0;
for(int i=len-x+1;i<=len;i++) c[++lenc]=b[i];
}

inline bool check()
{
for(int i=1;i<=lenc;i++)
if(a[i]!=c[i]) return false;
return true;
}

inline void prep()
{
for(int i=0;i<m;i++)
for(int j=0;j<=9;j++)
{
getstring(i,j+'0');
for(int k=len;k>=0;k--)
{
if(k==m)
{
getsuf(k);
if(check()) break;
else continue;
}
getsuf(k);
if(check()) {zy.mt[k][i]++;break;}//转移反过来写!!
}
}
zy.x=zy.y=m-1;
ans.x=m-1; ans.y=0;
ans.mt[0][0]=1;
}

inline void go()
{
prep();
while(n)
{
if(n&1) ans=zy*ans;
zy=zy*zy;
n>>=1;
}
int res=0;
for(int i=0;i<m;i++) res+=ans.mt[i][0];
cout<<res%mod<<endl;
}

int main()
{
read(),go();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: