BZOJ 1009: [HNOI2008]GT考试【KMP上DP+矩阵快速幂

来源:互联网 发布:编程语言的种类 编辑:程序博客网 时间:2024/05/14 12:39

很明显是个AC自动机/KMP上的数位dp

看数据范围是要用矩阵优化的

乱搞推矩阵……这种技能……大概需要意会QwQ……

考虑最暴力的做法,f[i][j]表示长度为n的串匹配到了第i位,且此时在KMP上匹配到了第j个字符

如果转移,在目前的已经匹配的串后面加一个字符,肯定就是直接用KMP匹配的姿势,反正字符集只有0到9,于是暴力枚举在后面加某个数会发生的转移就好了


然后会发现,向量f[i]只和向量f[i-1]的值相关,于是可以用矩阵优化了

……推矩阵……啊…………QAQ

反正把系数填进去就好了…………………………吧…………………………???

根据矩阵乘法的计算方式,相当于是个求和的式子啊


WA了一年……发现是kmp写错了+取模那儿打错了于是爆int了【跪地不起

这个题都wa的flaze被裱惨了QwQ


#include<bits/stdc++.h>#define MAXN 25//#define Flaze_naiveusing namespace std;int n,m,K;char s[MAXN];int fail[MAXN];void KMP(){for(int i=1,j=0;i<=m;++i){for(j=fail[i];j&&s[j+1]!=s[i+1];j=fail[j]);if(s[i+1]==s[j+1])++j;fail[i+1]=j;}#ifdef Flaze_naivefor(int i=1;i<=m;++i)printf("%c %d\n",s[i],fail[i]);#endif}struct matrix{int d[MAXN][MAXN];int x,y;void write(){for(int i=0;i<x;++i){for(int j=0;j<y;++j)printf("%d ",d[i][j]);puts("");}puts("");}matrix():x(0),y(0){memset(d,0,sizeof d);}matrix(int a):x(a),y(a){memset(d,0,sizeof d);for(int i=0;i<a;++i)d[i][i]=1;}matrix(int a,int b):x(a),y(b){memset(d,0,sizeof d);}matrix operator * (const matrix ano){matrix RTN(x,ano.y);for(int i=0;i<x;++i)for(int j=0;j<y;++j)for(int k=0;k<ano.y;++k)RTN.d[i][k]+=d[i][j]*ano.d[j][k],RTN.d[i][k]%=K;#ifdef Flaze_naiveRTN.write();#endifreturn RTN;}matrix pow(int cf){matrix RTN(x),TMP=*this;for(;cf;cf>>=1){if(cf&1)RTN=RTN*TMP;TMP=TMP*TMP;}return RTN;}}A,B;void build_B(){B=matrix(m,m);for(int i=0;i<m;++i){for(int j=0;j<10;++j){int pos=i;while(pos&&s[pos+1]!=j+'0')pos=fail[pos];if(s[pos+1]==j+'0')++pos;++B.d[pos][i];}}}void build_A(){A=matrix(m,1);A.d[0][0]=1;}int mod_pow(int d,int c){int rtn=1,tmp=d;for(;c;c>>=1){if(c&1)rtn*=tmp,rtn%=K;tmp*=tmp,tmp%=K;}return rtn;}int main(){scanf("%d%d%d",&n,&m,&K);scanf("%s",s+1);m=strlen(s+1);KMP();build_A();build_B();#ifdef Flaze_naiveB.write();#endifA=B.pow(n)*A;/* A.write();for(int i=1;i<=n;++i){A=B*A;A.write();}*/int ans=0;for(int i=0;i<m;++i) ans+=A.d[i][0],ans%=K;printf("%d",ans);return 0;} /*4 6 100123123*/


0 0
原创粉丝点击