BZOJ 1009-GT考试(kmp+矩阵快速幂+DP)
来源:互联网 发布:linux 内核版本 编辑:程序博客网 时间:2024/06/08 10:18
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3921 Solved: 2393
[Submit][Status][Discuss]
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
111
Sample Output
HINT
Source
这道题着实让我搞了一下午,本来的第一感觉应该是数位DP的,但是n足足有10^9这么大,果断行不通啊。。。。
想了想感觉像是需要矩阵优化一发,推了一发递推式,后来感觉还是漏洞百出,无奈之下还是查看了题解。
题解也是看的我一脸懵逼,但是杠了将近一下午,总算是明白了不少。。。。
其实递推关系式还是很容易想到的,当前位一定只和前一位有关,可是如何能不重复的避免出现不幸运数字呢。。
这里参考的是一位大神的思路(仅供参考):
按顺序处理准考证号每一位,
设f[i][j]表示:准考证号前i位中 后j位与不吉利数的前j位相同时,前i位的方案数
那么答案ans=f[n][0]+f[n][1]+…+f[n][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]求法是个线性齐次递推式,可以构造成矩阵
#include<map>#include<stack>#include<queue>#include<vector>#include<math.h>#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>using namespace std;typedef long long ll;#define maxn 400004int k,n,m,p[maxn],hashs[maxn];char str[maxn];struct node{ int s[50][50]; node() { memset(s,0,sizeof(s)); }}a,z;node multi(node a,node b){ node res; int i,j,kk; for(i=0;i<m;i++) for(j=0;j<m;j++) { for(kk=0;kk<m;kk++) res.s[i][j]=(res.s[i][j]+a.s[i][kk]*b.s[kk][j])%k; res.s[i][j]%=k; } return res;}node work(node x,int y){ int i,j; node res; for(i=0;i<m;i++) for(j=0;j<m;j++) if(i==j) res.s[i][j]=1; while(y) { if(y%2) res=multi(res,x); x=multi(x,x); y/=2; } return res;}int main(void){ int i,j,ans=0; scanf("%d%d%d",&n,&m,&k); scanf("%s",str+1); p[1]=p[2]=1; for(i=2;i<m;i++) { j=p[i]; while(j>1 && str[j]!=str[i]) j=p[j]; if(str[j]==str[i]) p[i+1]=j+1; else p[i+1]=1; } z.s[0][0]=1; for(i=0;i<m;i++) { j=i+1; int sum=a.s[i][j]=1; hashs[str[j]]=i+1; while(j!=1) { j=p[j]; if(hashs[str[j]]!=i+1) { a.s[i][j]=1; hashs[str[j]]=i+1; sum++; } } a.s[i][0]=10-sum; } z=multi(z,work(a,n)); for(i=0;i<m;i++) ans=(ans+z.s[0][i])%k; printf("%d\n",ans); return 0;}
- BZOJ 1009-GT考试(kmp+矩阵快速幂+DP)
- BZOJ 1009 GT考试 KMP+DP+矩阵快速幂
- bzoj 1009: [HNOI2008]GT考试(dp+kmp+矩阵快速幂)
- BZOJ 1009: [HNOI2008]GT考试(DP+KMP失配+矩阵快速幂)
- [省选前题目整理][BZOJ 1009][HNOI 2008]GT考试(KMP+DP+矩阵快速幂)
- [KMP DP 矩阵快速幂加速] BZOJ 1009 [HNOI2008]GT考试
- BZOJ 1009: [HNOI2008]GT考试【KMP上DP+矩阵快速幂
- BZOJ KMP+矩阵快速幂 1009: [HNOI2008]GT考试
- BZOJ 1009 GT考试 KMP+矩阵快速幂.
- BZOJ 1009 GT考试 DP+矩阵快速幂
- BZOJ 1009([HNOI2008]GT考试-KMP+矩阵加速Dp)
- 【BZOJ】1009 [HNOI2008]GT考试 KMP+DP+矩阵优化
- [BZOJ 1009][HNOI2008]GT考试(KMP+线性齐次递推的矩阵加速?+DP)
- [KMP+矩阵快速幂加速]BZOJ 1009——[HNOI2008]GT考试
- [bzoj 1009] [HNOI2008]GT考试:DP,单串AC自动机,矩阵快速幂
- BZOJ 1009: [HNOI2008]GT考试 AC自动机+矩阵快速幂
- bzoj1009[GT考试] dp+矩阵快速幂
- BZOJ 1009 KMP,DP,矩阵快速幂
- mysql忘记root密码
- 前端学习历程
- 几种进程间的通信方式
- Java数组
- 热管理设计Taitherm (ex-Radtherm) v12.1.1 Win64 & Linux64 2CD
- BZOJ 1009-GT考试(kmp+矩阵快速幂+DP)
- 1.并发编程—— 线程安全(一)
- 网页爬虫-用PHP的拓展库curl实现模拟登录慕课网
- 并发
- 视图控制器的生命周期方法
- Qt绘图程序
- classpath、path、JAVA_HOME的作用及JAVA环境变量配置
- hadoop计算单词出现次数
- 跟我一学linux基础(第四天)