您的位置:首页 > 其它

BZOJ 1009 [HNOI2008]GT考试

2018-03-20 21:31 323 查看
设dp[i][j]为当前是第i位考号、现在匹配到A的第j位的方案数

因为假如当前匹配j位,如果选择的下一位与A[j+1]不同,新的匹配位数是num(fail[j])而不是0

设由匹配j位转移到匹配k位的方案数为c[j][k]那么

$dp[i][j] = \sum f[i-1][k]*c[k][j] $

这个式子是线性的,计算出t矩阵的n次幂,乘以初始矩阵
c矩阵枚举当前匹配多少位,利用KMP计算c矩阵

#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 33;
int n,m,k,T[maxn],next[maxn];
struct Matrix {
int f[maxn][maxn];
Matrix () { memset(f,0,sizeof f);};
void clear() { memset(f,0,sizeof f);};
}a,F;
Matrix operator * (const Matrix & a,const Matrix & b) {
Matrix ret;
for(int i=0;i<m;++i)
for(int j=0;j<m;++j)
for(int kk=0;kk<m;++kk)
ret.f[i][j]=(ret.f[i][j]+a.f[i][kk]*b.f[kk][j])%k;
return ret;
}
void get_next() {
next[1]=0;
for(int j=0,i=2;i<=m;++i) {
for(;j && T[j+1] != T[i];j=next[j]);
if(T[j+1]==T[i]) ++j; next[i]=j;
}
}
void get_a() {
for(int i=0;i<m;++i)
for(int k,j=0;j<10;++j) {
for(k=i; k && T[k+1]!=j; k=next[k]);
if(T[k+1]==j) ++k;
a.f[i][k]++;
}
}
void pow() {
Matrix tmp=a;
a.clear();
for(int i=0;i<m;++i) a.f[i][i]=1;
for(;n;n>>=1,tmp=tmp*tmp) if(n&1) a=a*tmp;
}
int main() {
char c[maxn];
scanf("%d%d%d%s",&n,&m,&k,c+1);
for(int i=1;i<=m;++i) T[i]=c[i]-'0';
get_next();get_a();pow();
int Ans=0;
F.f[0][0]=1;
F=F*a;
for(int i=0;i<m;++i) Ans=(Ans+F.f[0][i])%k;
printf("%d\n",Ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: