[HNOI2008] GT考試
阿新 • • 發佈:2018-09-21
前綴 close spa 矩陣乘法 pre 分享 方法 long %d
又是一道用KMP的字符串DP。
洛谷 P3193 傳送門
bzoj 1009 傳送門
設f[i][j]為主串匹配到第i位,模式串最多匹配到第j位的方案數。
令g[i][j]表示模式串的前綴i可以轉移到前綴j的方法數。
則:f[i][j]=(f[i-1][0]+f[i-1][1]+...+f[i-1][m-1])*g[k][j]。
用矩陣乘法優化一下遞推即可。
1 #include<cstdio> 2 3 int n,m,mod; 4 char s[25]; 5 int nx[25]; 6 7 void getnx() 8 { 9 for(int i=2,j=1GT考試;i<=m+1;) 10 { 11 nx[i]=j; 12 while(j&&s[i]!=s[j])j=nx[j]; 13 i++,j++; 14 } 15 } 16 17 struct matrix 18 { 19 int a[25][25]; 20 }f,g; 21 22 matrix multi(matrix q,matrix w) 23 { 24 matrix e; 25 for(int i=0;i<m;i++) 26 { 27 for(int j=0;j<m;j++) 28 { 29 e.a[i][j]=0; 30 for(int k=0;k<m;k++) 31 { 32 e.a[i][j]=(e.a[i][j]+q.a[i][k]*w.a[k][j]%mod)%mod; 33 } 34 } 35 } 36 return e; 37 } 38 39 matrix ksm(matrix q,int t) 40 { 41 matrix ret=q; 42 t--;43 while(t) 44 { 45 if(t&1)ret=multi(ret,q); 46 q=multi(q,q); 47 t>>=1; 48 } 49 return ret; 50 } 51 52 int main() 53 { 54 scanf("%d%d%d",&n,&m,&mod); 55 scanf("%s",s+1); 56 getnx(); 57 for(int i=0;i<m;i++) 58 { 59 for(int j=0;j<10;j++) 60 { 61 int p=i; 62 while(p&&s[p+1]!=j+‘0‘)p=nx[p+1]-1; 63 if(s[p+1]==j+‘0‘)p++; 64 if(p!=m)g.a[p][i]=(g.a[p][i]+1)%mod; 65 } 66 } 67 f=ksm(g,n); 68 long long ans=0; 69 for(int i=0;i<m;i++)ans=(ans+f.a[i][0])%mod; 70 printf("%lld",ans); 71 return 0; 72 }
寫的時候,矩陣乘法忘打return了,調了半天都輸出0......
後來Dr_J幫我找出了這個沙雕錯誤......
[HNOI2008] GT考試