【BZOJ】【1009】 【HNOI2008】GT考试
DP/KMP/矩阵乘法
好神的题啊……跪了跪了
$n\leq 10^9$是什么鬼……我们还是先不要考虑这个鬼畜的玩意了>_>
用类似数位DP的思路,我们可以想到一个DP方程:$f[i][j]$表示前 i 位数字,它的最后 j 位与不吉利串匹配的方案数,显然有$ans=\sum_{i=0}^x f[n][i]$
然后就是转移的问题了= =那么依旧按照数位DP的想法(其实是硬扯到那的吧……怎么理解都可以,重点是明白转移方程)可以想到:从 i 转移到 i+1,有10种方案,其中一种会使得匹配长度+1,即$f[i+1][j+1]+=f[i][j]$那么其他的方案呢?并不都会使得匹配长度归0,想到这你大概已经想到了,对!就是KMP!字符串匹配时的fail指针!那么转移的方式就是这三种了= =:1.匹配长度归0;2.匹配长度+1;3.匹配长度变为fail[j]+1。
那么转移方式已经确定啦~接下来就该考虑一下$n\leq 10^9$这个蛋疼的范围了……
很明显这个范围O(n)是不可能的了= =必须要加速!那么我们来研究一下这个转移:我们可以把$f_i$看作一个向量:$$\begin{bmatrix} f_0 f_1 \cdots f_{m-1} \end{bmatrix}(即0\leq j\leq m-1) $$ 从$f_i$转移到$f_{i+1}$,其实是可以用一个矩阵来表示的: $$ \begin{bmatrix} f_0& f_1 &\cdots &f_{m-1} \end{bmatrix}_{i} * \begin{bmatrix} a_{0,0}& a_{0,1}& \cdots &a_{0,m-1} \\ a_{1,0}& a_{1,1}& \cdots &a_{1,m-1} \\ \ddots& \ddots& \vdots &\ddots \\ a_{m-1,0}& a_{m-1,1}& \cdots &a_{m-1,m-1} \end{bmatrix} = \begin{bmatrix} f_0 &f_1 &\cdots &f_{m-1} \end{bmatrix}_{i+1} $$
嗯左边的表示$f[i][j]$,右边就是$f[i+1][j]$了;那么a矩阵是什么玩意呢?这是一个转移矩阵:$a[i][j]$表示从匹配了 i 个字符转移到匹配了 j 个字符有多少种方案!很明显当$j>0$的时候f[i][j]只可能是0或1,这里可能需要仔细理解一下,反正$f[i+1]$跟$f[i]$是线性相关的!所以我们可以直接利用矩阵乘法加速!
嗯这道题我写的时候由于本题有【匹配长度为0】这个状态……然后KMP很久没写过了……果断跪啊,这题貌似是需要在原来的KMP上稍微改动一下,由于我KMP理解的不是很好所以蛋疼了很久……最后是看了Hzwer的写法才过的
/**************************************************************
Problem: 1009
User: Tunix
Language: C++
Result: Accepted
Time:56 ms
Memory:812 kb
****************************************************************/ //BZOJ 1009
#include<cstdio>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
const int N=,INF=~0u>>;
/******************tamplate*********************/
int n,m,P;
struct Matrix{
int x[N][N];
int* operator [] (int a) {return x[a];}
Matrix(int a=){
rep(i,N) rep(j,N)
if (i==j) x[i][j]=a;
else x[i][j]=;
}
};
Matrix operator*(Matrix a,Matrix b){
Matrix c;
rep(i,m) rep(j,m) rep(k,m)
c[i][j]=(c[i][j]+a[i][k]*b[k][j])%P;
return c;
}
Matrix Pow(Matrix a,int b){
Matrix r();
for(;b;b>>=,a=a*a) if(b&) r=r*a;
return r;
}
/*******************Matrix**********************/
char s[];
Matrix f,a;
int next[];
void KMP(){
int j=;
F(i,,m){
while (j && s[i]!=s[j+]) j=next[j];
if (s[j+]==s[i]) j++;
next[i]=j;
}
rep(i,m)
rep(j,){
int x=i;
while(x && s[x+]-''!=j) x=next[x];
if (j==s[x+]-'') a[i][x+]++;
else a[i][]++;
}
}
int main(){
scanf("%d%d%d",&n,&m,&P);
scanf("%s",s+);
KMP();
f=Pow(a,n);
int ans=;
rep(i,m) ans+=f[][i],ans%=P;
printf("%d\n",ans);
return ;
}
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 2015 Solved: 1233
[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位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6
Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.
Sample Input
111
Sample Output
HINT
Source
【BZOJ】【1009】 【HNOI2008】GT考试的更多相关文章
- BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )
写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j) ...
- BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4266 Solved: 2616[Submit][Statu ...
- bzoj 1009: [HNOI2008]GT考试 -- KMP+矩阵
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MB Description 阿申准备报名参加GT考试,准考证号为N位数X1X2.. ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
- bzoj 1009 [HNOI2008]GT考试(DP+KMP+矩阵乘法)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1009 [题意] 给定一个字符串T,问长度为n且不包含串T的字符串有多少种. [思路] ...
- BZOJ 1009: [HNOI2008]GT考试(kmp+dp+矩阵优化)
http://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 思路:真的是好题啊! 对于这种题目,很有可能就是dp,$f[i][j]$表示分析到第 ...
- bzoj 1009 [HNOI2008]GT考试——kmp+矩阵优化dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 首先想到 确保模式串不出现 就是 确保每个位置的后缀不是该模式串. 为了dp,需要记录 ...
- 题解:BZOJ 1009 HNOI2008 GT考试 KMP + 矩阵
原题描述: 阿申准备报名参加GT考试,准考证号为N位数 X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学A1A2...Am(0<=Ai&a ...
- bzoj 1009:[HNOI2008]GT考试
这道题机房n多人好久之前就A了…… 我到现在才做出来…… 一看就是DP+矩阵乘法,但是一开始递推式推错了…… 正确的递推式应该是二维的…… f[i][j] 表示第准考证到第 i 位匹配了 j 位的方案 ...
- BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法
标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...
随机推荐
- Java Executor并发框架(一)整体介绍
一.概述 Java是天生就支持并发的语言,支持并发意味着多线程,线程的频繁创建在高并发及大数据量是非常消耗资源的,因为java提供了线程池.在jdk1.5以前的版本中,线程池的使用是及其简陋的,但是在 ...
- Android事件分发机制完全解析,带你从源码的角度彻底理解
Android事件构成 在Android中,事件主要包括点按.长按.拖拽.滑动等,点按又包括单击和双击,另外还包括单指操作和多指操作.所有这些都构成了Android中的事件响应.总的来说,所有的事件都 ...
- cocoaPod相关问题
cocoap简介: 1. 简介 CocoaPods是一个负责管理iOS项目中第三方开源代码的工具,其源码在Github上开源.使用CocoaPods可以节省设置和更新第三方开源库的时间并提高工作效率. ...
- Knockout学习地址
Knockout.js是什么? Knockout是一款很优秀的JavaScript库,它可以帮助你仅使用一个清晰整洁的底层数据模型(data model)即可创建一个富文本且具有良好的显示和编辑功能的 ...
- SilverIight数据绑定实例
前台Code <DataGrid Name="DataGrid1" AutoGenerateColumns="False" IsReadOnly=&quo ...
- 微软职位内部推荐-Software Development Engineering II
微软近期Open的职位: Job Title: Software Development Engineering II Work Location: Suzhou, China Enterprise ...
- htaccess 增加静态文件缓存和压缩
增加图片视频等静态文件缓存: <FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf)$"> Header set Cache-Cont ...
- C语言 简单的栈
//简单的栈 #include<stdio.h> #include<stdlib.h> //栈的介绍:栈先进后出,一般用于将数据逆序输出 //栈一般只有四种方法--进栈,出栈, ...
- CAS 单点登录流程
经验:在网上学东西不要指望一篇文章就能让你明白——我在网上学CAS流程,看了五六篇博文,其中三篇是觉得作者表达能力不行,或者作者自己就没明白怎么回事就出来写东西,看到一半就跳过了,剩下两篇每篇看了两遍 ...
- Discuz X3核心文件解析
<?php /** * [Discuz!] (C)2001-2099 Comsenz Inc. * This is NOT a freeware, use is subjec ...