bzoj1009 [HNOI2008]GT考试
2017-03-18 22:42
423 查看
Description
阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0Input
第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.Sample Input
4 3 100111
Sample Output
81正解:$kmp$+矩阵快速幂加速。
cjk大神的题解:
字符串上的动态规划:
按顺序处理准考证号每一位,
设f[i][j]表示:准考证号前i位中 后j位与不吉利数的前j位相同时,前i位的方案数
那么答案ans=f
[0]+f
[1]+…+f
[m-1]
f[i][j]的准确含义:
1.f[i][j]表示的每种方案不仅与其后j位有关,还应保证不含不吉利数
2.为避免重复,f[i][j]表示的每种方案都不含长度大于j且与不吉利数的前缀相同 的后缀
否则就会出现:从1到m标号,不吉利数为123124时,f[i][2]计数的方案包含f[i][5]计数的方案 的情况
状态转移:
f[i][j]只能由f[i-1][k]得到,相当于填完第i-1位后,将其后缀k(长为k的后缀)后面新添一位num,之后这个i位数的 与不吉利数前缀相同的最长后缀是:后缀j
i>=1时:f[i][j]=f[i-1][0]*a[0][j]+f[i-1][1]*a[1][j]+…+f[i-1][m-1]*a[m-1][j]
比如:还是假设不吉利数为123124,那么 f[i][3]=f[i-1][2]+f[i-1][5],因为 f[i-1][2]末尾的*****12不能是**12312,所以需要f[i-1][5]补充
但若不吉利数为123123,那么 f[i][3]=f[i-1][2],因为 f[i][3]末尾的*****123不能是**123123
i==0时:f[0][0]=1,f[0][其他]=0
其中,a[k][j]就表示上面提到的num能取几个值,可以用kmp算法预处理出来,它是一个矩阵
这样就可以不重不漏地计数了
再来个矩阵加速:f[i][j]求法是个线性齐次递推式,可以构造成矩阵,然后加一下速。
感觉自己还不是很理解。。慢慢推敲吧。。
//It is made by wfj_2048~ #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf (1<<30) #define il inline #define RG register #define ll long long #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct data{ int a[30][30]; }a,b; int nxt[30],n,m,k,ans; char s[30]; il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; } il data mul(RG data a,RG data b){ RG data c; memset(c.a,0,sizeof(c.a)); for (RG int i=0;i<m;++i) for (RG int j=0;j<m;++j) for (RG int p=0;p<m;++p){ c.a[i][j]+=a.a[i][p]*b.a[p][j]%k; if (c.a[i][j]>=k) c.a[i][j]-=k; } return c; } il void work(){ n=gi(),m=gi(),k=gi(); scanf("%s",s+1); for (RG int i=2;i<=m;++i){ RG int j=nxt[i-1]; while (j && s[j+1]!=s[i]) j=nxt[j]; if (s[j+1]==s[i]) nxt[i]=j+1; } for (RG int i=0;i<m;++i) for (RG int j=0;j<=9;++j){ RG int t=i; while (t && s[t+1]!=j+'0') t=nxt[t]; if (s[t+1]==j+'0') t++; if (t!=m){ b.a[i][t]++; if (b.a[i][t]>=k) b.a[i][t]-=k; } } for (RG int i=0;i<m;++i) a.a[i][i]=1; while (n){ if (n&1) a=mul(a,b); b=mul(b,b); n>>=1; } for (RG int i=0;i<m;++i){ ans+=a.a[0][i]; if (ans>=k) ans-=k; } printf("%d\n",ans); return; } int main(){ File("gt"); work(); return 0; }
相关文章推荐
- BZOJ-1009-GT考试-HNOI2008
- BZOJ_1009_[HNOI2008]_GT考试_(动态规划+kmp+矩阵乘法优化+快速幂)
- 【bzoj1009】【HNOI2008】【GT考试】
- BZOJ 1009 【HNOI2008】 GT考试
- 【以前的空间】bzoj1009 [HNOI2008]GT考试
- BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)
- BZOJ1009 [HNOI2008]GT考试【kmp+矩阵加速DP】
- 【BZOJ1009】【HNOI2008】GT考试 AC自动机+矩阵乘法
- BZOJ 1009:[HNOI2008]GT考试
- 【BZOJ1009】【HNOI2008】GT考试
- bzoj 1009: [HNOI2008]GT考试(AC自动机+矩阵优化dp)
- [BZOJ1009][HNOI2008]GT考试(AC自动机+dp+矩阵优化)
- BZOJ 1009 [HNOI2008]GT考试 - KMP+计数DP+矩阵快速幂优化
- BZOJ 1009: [HNOI2008]GT考试【KMP上DP+矩阵快速幂
- 【DP+KMP+矩阵乘法】BZOJ1009(HNOI2008)[GT考试]题解
- BZOJ1009: [HNOI2008]GT考试
- bzoj 1009: [HNOI2008]GT考试
- BZOJ 1009 [HNOI 2008] GT考试
- BZOJ 1009 [HNOI2008]GT考试
- [BZOJ 1009][HNOI2008]GT考试(KMP+线性齐次递推的矩阵加速?+DP)