【2018.10.10】[HNOI2008] GT考试(bzoj1009)
10pts:
暴力枚举字符串,Hash判是否出现。(真会有人写么)
时间复杂度$O(10^n*n)$。
40pts:
学过OI的人都会写的dp
如果这道题的40pts($n\le 250000$)设成100pts的话那就是水的一批的提高组题目了。可惜这是省选题目
设$f(i,j)$表示以准考证号为基准递推,准考证号匹配到第$i$位,不吉利数字匹配到第$j$位时(即准考证的后$j$位等于不吉利数字的前$j$位),不出现不吉利数字的字符串数量。
发现$m$只有20,$n*m$的dp可过。
那怎么转移?
既然要以考号为基准递推,就要考虑一位考号对下一位的影响。
而考号是可以随便写的,那我们就要考虑10种数字了。
对于一个新数字$new$,有以下几种情况:
1.$new$与不吉利数字的$j+1$位匹配,$dp(i+1,j+1)$的答案数+dp(i,j)
2.上述两者不匹配。
不匹配怎么办?这个不匹配的$new$一定没有贡献了?
当然不一定。
你有没有听说过一个叫$AC$自动机的垃圾。
啥,你没听说过?那放水点,你有没有听说过一个叫$KMP$的垃圾。
可能存在与$new$后缀与它相同的不吉利数字前缀,而这些前缀位置是要被更新答案的。
怎么讲呢,举个例子吧,不吉利数字是$12212112$。
然后你的准考证号枚举到第$9$位时,前面$8$位已经枚举成了$11112212$。可以发现已经匹配了不吉利数字的前$5$位,现在要匹配第$6$位。
如果第$9$位枚举$1$,那它就匹配了,$dp(9,6)+=dp(8,5)$。
如果第$9$位枚举$2$,那它就不匹配。但是会发现,存在 与当前已匹配的不吉利数字的后缀相同 的前缀,可以匹配上这个$2$!
上一个位置就是不吉利数字的第$2$位。
它的下一位,第$3$位$2$,刚好可以匹配枚举的第$9$位!
所以此时最多能匹配不吉利数字的前$3$位,有转移$dp(9,3)+=dp(8,5)$。
2019.8.23 update:这段好像解释错了,建议无视
我们只需要沿着不吉利数字的失配指针往前走,找到第一个下一位与$new$匹配的位置就可以了。
为什么不用考虑再往前的下一位可以匹配$new$的位置?
因为这是递推,从前往后每一种状态都会被考虑,所以在考虑匹配后面的位之前,前面的位已经匹配好更前面的情况了。
比如不吉利数字$1221221211$。你目前枚举的准考证号前$8$位是$12212212$,现在你要枚举第$9$位。
很明显当枚举$2$时,通过找不吉利数字中 后缀相同的前缀,可知$dp(8,8)$可以转移到$dp(9,6)$。
但是我们发现也可以转移到$dp(9,3)$诶!
事实上,在这之前$dp(8,5)$已经转移到$dp(9,3)$过了。而$dp(8,5)$表示什么?它表示准考证号枚举8位,后$5$位与不吉利数字的前$5$位匹配上。
$dp(8,8)$同理,表示准考证号枚举前$8$位,后$8$位与不吉利数字的前$5$位匹配上。
这样直观看起来没什么答案关联。但是仔细考虑以下,不吉利数字的第$8$位的失配指针指向第$5$位。
这说明什么?
不吉利数字的前$8$位中,前$5$位等于后$5$位!
还不够直观,能再明白点么?
匹配$5$位的情况包含匹配$8$位的情况!(因为你匹配了$8$位,根据上推论可知也算在匹配了$5$位的情况中)
这就是别人博客中此题题解经常提到的计数方案会包含的问题。蒟蒻之前也一直没看懂,想了一通才明白……
所以我们在转移时,把$dp(8,8)$的情况加给$dp(8,5)$,然后让$dp(8,5)$捎带加给$dp(9,3)$。
其实按照$AC$自动机的构造方式,如果一个点没有字符为$new$的儿子边的话,它会建出一条对应的虚拟儿子边和点,儿子点上存的是沿着失配指针往回走的上一个实际存在这条字符边所指向的儿子。
当然这题$m$很小,不吉利数字串自己匹配自己的复杂度很小,可以直接暴力跑失配指针找第一个。
转移就这样
$dp[i+1][j]=\sum_{0<=k<=m-1}dp[i][k] \times g[k][j]$
其中$g(i,j)$表示准考证号匹配不吉利数字的前$i$位时,准考证号增加一个字符,使不吉利数字沿失配指针(自己也可以)找到的最大的匹配位数$j$(算上新匹配的一位)的方案数。
$dp$套$dp$?
其实不用,不吉利数字已经知道了,$g$数组可以预处理出来($KMP$)。
注意一个事情,沿着失配指针走时,可能找不到与准考证号枚举位匹配的位置。此时新的最大匹配位数是$0$,仍然可以转移!
时间复杂度$O(n*m^2)$。
100pts:
然后我们惊奇地发现$n\le 10^9$,不让你循环推,直接就想到矩阵快速幂优化了。
观察一下转移方程,发现$dp[i+1][?]$总是由$dp[i][?]$推来,而且$i$还是$n$这个级别的。
又发现每次实际上都是乘一个固定的矩阵$g$,也就是说整个$dp$数组的某一位的值其实都是通过一些$g$数组乘过来的。
所以可以把$dp$数组直接当成$g$数组自己乘自己。
比如说,$g(4,2)=4$。
表示有4种转移情况可以让 与不吉利数字的前4位匹配的情况 在准考证号增加1位后 与不吉利数字的前2位匹配。
所以$dp(x+1,2)=dp(x,4)*g(4,2)=dp(x,4)*4$ | $x$是正整数。
而$dp(x,4)$又是哪来的?
它是通过$\sum_{i=1}^{m}dp(x-1,i)*g(i,4)$转移过来的。
所以一直往前推到x=0,发现$dp$值的$n$次转移都只跟转移矩阵$g$有关,是否与不吉利数字完全匹配等情况可以在弄$g$数组时就处理掉,即$g$数组只考虑不吉利数字被匹配$0$~$m-1$位的情况,不让它转移到$j$位都被匹配的情况。
所以就是对$g$矩阵做快速幂,求它的$n$次方。
时间复杂度$O(log(n)*m^3)$,有点常数。
最后说明:
1. 为什么答案是$\sum_{i=0}^{j-1}g(0,i)$:
考虑$g(i,j)$的意义。如果$g$矩阵自己对自己连续进行$k$次转移(不进行快速幂而循环推),$g(i,j)$就表示:在进行$k$次转移前 准考证号匹配不吉利数字的前$i$位时,准考证号增加$k$个字符后,使不吉利数字沿失配指针(自己也可以)找到的最大的匹配位数$j$(算上新匹配的$k$位)的方案数。这是矩阵转移的基本概念。
所以进行$n$次转移后,$g(i,j)$就表示一开始准考证号匹配不吉利数字的前$i$位时,准考证号增加$n$个字符后,使不吉利数字沿失配指针(自己也可以)找到的最大的匹配位数$j$(算上新匹配的$k$位)的方案数。
我们需要取全局情况的答案,而这是很显然的。开始时准考证号匹配不吉利数字的前$0$位(准考证号还一位都没枚举),所以$i$为$0$;而由于已经定义过$g$数组只考虑不吉利数字被匹配 $0$~$m-1$ 位的情况,所以$j$在这个区间取任意值,$g(0,j)$都是答案的一部分。把它们都算上就是答案。
2. (2018.11.26 update)初始矩阵是一维线性矩阵,而不是二维的!之前一直以为是二维的导致理解很麻烦!
下面是code,不过我的转移矩阵$b$(就是$g$)的$i,j$维是反过来写的,即 匹配后的匹配位数 指向 匹配前的匹配位数。
#include<bits/stdc++.h>
#define M 21
#define ll long long
using namespace std;
inline int read(){
int x=; bool f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=;
for(; isdigit(c);c=getchar()) x=(x<<)+(x<<)+(c^'');
if(f) return x;
return -x;
}
int n,m,mod,Fail[M];
char ch[M];
ll a[M][M],b[M][M];
void mul(ll a[M][M],ll b[M][M]){
ll tmp[M][M];
for(int i=;i<m;++i)
for(int j=;j<m;++j){
tmp[i][j]=;
for(int k=;k<m;++k)
(tmp[i][j]+=a[i][k]*b[k][j])%=mod;
}
for(int i=;i<m;++i)
for(int j=;j<m;++j)
a[i][j]=tmp[i][j];
}
int main(){
n=read(),m=read(),mod=read();
scanf("%s",ch+);
int i,j=;
for(i=;i<=m;++i){
while(j> && ch[j+]!=ch[i]) j=Fail[j];
if(ch[j+]==ch[i]) ++j;
Fail[i]=j;
}
int t;
for(i=;i<m;++i)
for(j=;j^;++j){
t=i;
while(t> && ch[t+]-''!=j) t=Fail[t];
if(ch[t+]-''==j) ++t;
if(t^m) b[t][i]=(b[t][i]+)%mod;
}
for(i=;i<m;++i) a[i][i]=;
while(n){
if(n&) mul(a,b);
mul(b,b);
n>>=;
}
ll sum=;
for(i=;i^m;++i) (sum+=a[i][])%=mod;
printf("%lld\n",sum);
return ;
}
【2018.10.10】[HNOI2008] GT考试(bzoj1009)的更多相关文章
- BZOJ1009 [HNOI2008]GT考试 矩阵
去博客园看该题解 题目 [bzoj1009][HNOI2008]GT考试 Description 阿申准备报名参加GT考试,准考证号为N位数X1X2….Xn(0<=Xi<=9),他不希望准 ...
- 【BZOJ1009】[HNOI2008]GT考试 next数组+矩阵乘法
[BZOJ1009][HNOI2008]GT考试 Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的 ...
- [BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂)
[BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂) 题面 阿申准备报名参加GT考试,准考证号为N位数X1X2-.Xn,他不希望准考证号上出现不吉利的数字.他的不吉利数学A ...
- 【bzoj1009】[HNOI2008]GT考试
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3018 Solved: 1856[Submit][Statu ...
- bzoj1009 [HNOI2008] GT考试 矩阵乘法+dp+kmp
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4542 Solved: 2815[Submit][Statu ...
- [Bzoj1009][HNOI2008]GT考试(KMP)(矩乘优化DP)
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4309 Solved: 2640[Submit][Statu ...
- 申请Office 365一年免费的开发者账号攻略(2018年10月份版本)
要进行Office 365开发,当然需要有完整的Office 365环境才可以.为了便于广大开发人员快速地启动这项工作,微软官方给所有开发人员提供了免费的一年开发者账号 那么如何申请Office ...
- IntelliJ IDEA 最新激活码(截止到2018年10月14日)
IntelliJ IDEA 注册码: EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEwMUlXU1dEIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYX ...
- 新手C#SQL Server使用记录2018.08.10
主键(PrimaryKey):主键就是每个数据行(记录)的唯一标识,不会有重复值的列(字段)才能当做主键.一个表可以没有主键,但是这样会很难处理表,因此一般情况表都要设置主键. 主键有两张选用策略,分 ...
随机推荐
- 洛谷 P1168 中位数
题目描述 给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[3], …, A[2k - 1]的中位数.[color=red]即[/color] ...
- 将从SQL2008 r2里备份的数据库还原到SQL2008中
从标题可以看出这是未解决上一篇遗留问题写的,现在我也不知道这个可不可以成功,方法似乎查到了一种,具体怎样还不清楚:而且,我想说的是“我踩雷了”. 这篇的主角是“Database Publishing ...
- FTP的环境搭建和防火墙设置
步骤: 1.右键点击无线网--->打开网络和共享中心--->控制面板--->程序--->启用或关闭Wondows功能
- 使用JDK自带的工具jstack找出造成运行程序死锁的原因
Java多线程编程也是Java面试中经常考察的内容.刚接触Java多线程编程的朋友们,可能会不慎写出一些会导致死锁(deadlock)的应用出来.如何分析造成Java多线程的原因呢?很多时候我们在怀疑 ...
- access处理重复创建表的方法。
第一种,使用MSysObjects表查找表名为当前创建表的名字的内容,相当于普通查询,但是access数据库有一个安全问题,就是有时候一开始是没有权限去调这些系统表的,这时可以再2007的access ...
- maven项目jsp无法识别jstl的解决办法
EL表达式无效是因为maven项目的jsp不识别jstl,只要在web-APP 标签中引入命名空间 xmlns="http://xmlns.jcp.org/xml/ns/javaee&quo ...
- 解决IIS7多域名绑定同一物理目录,设置不同的默认文档的问题
IIS7多域名绑定同一物理目录,设置不同的默认文档是没办法设置的,因为在一个物理目录下只有一个web.config,并且IIS7把默认文档设置写在这里,导致所有域名的默认文档设置共享.解决方法:1.进 ...
- NSLocale
1.创建本地化对象 // 根据本地标识符创建本地化对象 NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier"e ...
- 表单input中提示文字value随鼠标焦点移进移出而显示或隐藏的
jQuery代码 <input value="请输入用户名" type="text"> <input value="请输入密码&qu ...
- 学习笔记之30个常用的maven命令
maven 命令的格式为 mvn [plugin-name]:[goal-name],可以接受的参数如下, -D 指定参数,如 -Dmaven.test.skip=true 跳过单元测试: -P 指定 ...