[bzoj1009][kmp][DP][矩阵乘法]GT考试
2017-11-19 14:53
169 查看
Description
阿申准备报名参加GT考试,准考证号为N位数X1X2….Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。
他的不吉利数学A1A2…Am(0<=Ai<=9)有M位,不出现是指X1X2…Xn中没有恰好一段等于A1A2…Am.
A1和X1可以为 0
Input
第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000
Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.
Sample Input
4 3 100
111
Sample Output
81
题解
好久之前的题了。。
第一眼看这题。。是不是不知所措!是你就对了,因为我就是这样的
首先观察一下题目,简化题意就是一个给定长度的串,要求这个串里面不包含另一个给出的串,求这种串有多少个。Kmp!
暴力就可以枚举所有串的情况然后kmp。。当然这样会爆炸
高级一点的,我们来个Dp
设f[i][j]为 长度为i的母串的后缀与子串匹配到了j个长度的方案数
很明显,答案就是Sigma(f
[0]~f
[m-1])对吧
再给出一个数组w[i][j],表示在子串长度为i的前缀后加一个数,使这个前缀+这个数所组成的串与子串从头开始所能匹配的长度为j的方案数
转移方程就是f[i][j]*w[j][k]->f[i+1][k]
这样的复杂度就是n*m^2的,时间空间都会炸
考虑优化,转移方程中可以看出f[i+1]只会与f[i]有关,那么可以滚动。空间过得去时间过不去而已
你既然都想到空间优化居然想不到时间可以矩乘
每个f[i][j]都要乘w[j]这个数组给后面做贡献,且w数组是不变的。那么就矩乘优化啦!
代码中可以直接用转移矩阵代替w矩阵,因为转移矩阵其实就是w矩阵调转一个方向。至于为什么这样我推荐你手推一下矩阵
有个小槽点,w[i][m]这个状态是不能继承的,因为这样母串中一定会出现子串。而w[i][0]这个状态可继承。所以矩乘的时候枚举为0~m-1
阿申准备报名参加GT考试,准考证号为N位数X1X2….Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。
他的不吉利数学A1A2…Am(0<=Ai<=9)有M位,不出现是指X1X2…Xn中没有恰好一段等于A1A2…Am.
A1和X1可以为 0
Input
第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000
Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.
Sample Input
4 3 100
111
Sample Output
81
题解
好久之前的题了。。
第一眼看这题。。是不是不知所措!是你就对了,因为我就是这样的
首先观察一下题目,简化题意就是一个给定长度的串,要求这个串里面不包含另一个给出的串,求这种串有多少个。Kmp!
暴力就可以枚举所有串的情况然后kmp。。当然这样会爆炸
高级一点的,我们来个Dp
设f[i][j]为 长度为i的母串的后缀与子串匹配到了j个长度的方案数
很明显,答案就是Sigma(f
[0]~f
[m-1])对吧
再给出一个数组w[i][j],表示在子串长度为i的前缀后加一个数,使这个前缀+这个数所组成的串与子串从头开始所能匹配的长度为j的方案数
转移方程就是f[i][j]*w[j][k]->f[i+1][k]
这样的复杂度就是n*m^2的,时间空间都会炸
考虑优化,转移方程中可以看出f[i+1]只会与f[i]有关,那么可以滚动。空间过得去时间过不去而已
你既然都想到空间优化居然想不到时间可以矩乘
每个f[i][j]都要乘w[j]这个数组给后面做贡献,且w数组是不变的。那么就矩乘优化啦!
代码中可以直接用转移矩阵代替w矩阵,因为转移矩阵其实就是w矩阵调转一个方向。至于为什么这样我推荐你手推一下矩阵
有个小槽点,w[i][m]这个状态是不能继承的,因为这样母串中一定会出现子串。而w[i][0]这个状态可继承。所以矩乘的时候枚举为0~m-1
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct matrix { int m[25][25]; matrix(){memset(m,0,sizeof(m));} }st; int n,m,Mod; matrix multi(matrix u,matrix v,int n,int m,int p) { matrix ret; for(int i=0;i<n;i++) for(int j=0;j<m;j++) for(int k=0;k<p;k++) ret.m[i][k]=(ret.m[i][k]+u.m[i][j]*v.m[j][k])%Mod; return ret; } matrix pow_mod(matrix u,int b) { matrix ans; for(int i=0;i<m;i++)ans.m[i][i]=1; while(b) { if(b%2==1)ans=multi(ans,u,m,m,m); u=multi(u,u,m,m,m);b/=2; } return ans; } int p[25];//前缀为i位加一位能转移到j位 方案数 char s[30]; void kmp() { int len=strlen(s+1); p[1]=0;int j; for(int i=2;i<=len;i++) { j=p[i-1]; while(s[j+1]!=s[i] && j>0)j=p[j]; if(s[i]==s[j+1])j++; p[i]=j; } for(int i=0;i<len;i++) for(int y=0;y<=9;y++) { int j=i; while(j>0 && s[j+1]-'0'!=y)j=p[j]; if(s[j+1]-'0'==y)j++; st.m[j][i]=(st.m[j][i]+1)%Mod; } } int main() { scanf("%d%d%d",&n,&m,&Mod); scanf("%s",s+1); kmp(); st=pow_mod(st,n); int ans=0; for(int i=0;i<m;i++)ans=(ans+st.m[i][0])%Mod; printf("%d\n",ans); return 0; }
相关文章推荐
- [矩阵乘法+KMP] BZOJ1009: [HNOI2008]GT考试
- [KMP DP 矩阵快速幂加速] BZOJ 1009 [HNOI2008]GT考试
- BZOJ1009 GT考试 (DP 矩阵乘法优化)
- BZOJ 1009 [HNOI2008]GT考试 ——矩阵乘法 KMP
- 1009: [HNOI2008]GT考试 矩阵乘法优化DP+KMP
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
- 【bzoj1009】[HNOI2008]GT考试 矩阵+kmp+DP
- [BZOJ 1009][HNOI2008]GT考试(KMP+线性齐次递推的矩阵加速?+DP)
- [BZOJ1009]HNOI2008 GT考试|KMP|递推|矩阵乘法
- [HNOI2008]BZOJ1009 GT考试 - 动态规划 - 矩阵乘法 - KMP
- 【BZOJ1009】GT考试(HNOI2008)-DP矩阵优化+KMP
- BZOJ1009: [HNOI2008]GT考试 矩阵快速幂+kmp+dp
- BZOJ 1009 [HNOI2008]GT考试 矩阵乘法+DP
- BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )
- _bzoj1009 [HNOI2008]GT考试【矩阵加速dp】
- [Bzoj1009][HNOI2008]GT考试(KMP)(矩乘优化DP)
- 【矩阵乘】【KMP】【HNOI 2008】【bzoj 1009】GT考试
- bzoj1009: [HNOI2008]GT考试 矩阵乘法
- 【矩阵加速】【数论】【KMP】[BZOJ1009][HNOI2008]GT考试
- [bzoj 1009] [HNOI2008]GT考试:DP,单串AC自动机,矩阵快速幂