bzoj1009: [HNOI2008]GT考试
好流弊的题啊
f[i][j]表示当前枚举到第i位,和不吉利数字匹配到第j位
mp[i][j]表示匹配到第i位,转移到第j位方案
那么f[i][j]=sigema f[i-1][k]*mp[k][j]
矩乘
{f[i-1][0]~f[i-1][m-1]}*mp={f[i][0]~f[i][m]}
mp可以用KMP处理
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int mod; char ss[110000];int len; int p[110000]; void KMP() { p[1]=0;int j=0; for(int i=2;i<=len;i++) { while(j!=0&&ss[i]!=ss[j+1])j=p[j]; if(ss[i]==ss[j+1])j++; p[i]=j; } } struct Matrix { int mp[30][30]; void clean(){memset(mp,0,sizeof(mp));} friend Matrix operator *(Matrix A,Matrix B) { Matrix C;C.clean(); for(int i=0;i<=20;i++) for(int j=0;j<=20;j++) for(int k=0;k<=20;k++) C.mp[i][j]=(C.mp[i][j]+(A.mp[i][k]*B.mp[k][j])%mod)%mod; return C; } }A,ans; bool v[20]; void initA() { A.clean(); for(int i=0;i<len;i++) { int num=0; memset(v,false,sizeof(v)); for(int j=i;j!=0;j=p[j]) if(j!=len&&v[ss[j+1]-'0']==false) A.mp[i][j+1]++,v[ss[j+1]-'0']=true,num++; if(v[ss[1]-'0']==false)A.mp[i][1]++,num++; A.mp[i][0]=10-num; } } void init1() { ans.clean(); ans.mp[1][0]=9,ans.mp[1][1]=1; } int main() { int n; scanf("%d%d%d",&n,&len,&mod); scanf("%s",ss+1);KMP(); initA();init1(); n--; while(n>0) { if(n%2==1)ans=ans*A; A=A*A;n/=2; } int sum=0; for(int i=0;i<len;i++)sum=(sum+ans.mp[1][i])%mod; printf("%d\n",sum); return 0; }
pain and happy in the cruel world.