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

4 3 100
111

Sample Output

81

HINT

Source

[Submit][Status][Discuss]

【BZOJ】【1009】 【HNOI2008】GT考试的更多相关文章

  1. BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )

    写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j) ...

  2. BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4266  Solved: 2616[Submit][Statu ...

  3. bzoj 1009: [HNOI2008]GT考试 -- KMP+矩阵

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MB Description 阿申准备报名参加GT考试,准考证号为N位数X1X2.. ...

  4. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  5. bzoj 1009 [HNOI2008]GT考试(DP+KMP+矩阵乘法)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1009 [题意] 给定一个字符串T,问长度为n且不包含串T的字符串有多少种. [思路] ...

  6. BZOJ 1009: [HNOI2008]GT考试(kmp+dp+矩阵优化)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 思路:真的是好题啊! 对于这种题目,很有可能就是dp,$f[i][j]$表示分析到第 ...

  7. bzoj 1009 [HNOI2008]GT考试——kmp+矩阵优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 首先想到 确保模式串不出现 就是 确保每个位置的后缀不是该模式串. 为了dp,需要记录 ...

  8. 题解:BZOJ 1009 HNOI2008 GT考试 KMP + 矩阵

    原题描述: 阿申准备报名参加GT考试,准考证号为N位数 X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学A1A2...Am(0<=Ai&a ...

  9. bzoj 1009:[HNOI2008]GT考试

    这道题机房n多人好久之前就A了…… 我到现在才做出来…… 一看就是DP+矩阵乘法,但是一开始递推式推错了…… 正确的递推式应该是二维的…… f[i][j] 表示第准考证到第 i 位匹配了 j 位的方案 ...

  10. BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法

    标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...

随机推荐

  1. Android代码优化----PullToRefresh+universal-image-loader实现从网络获取数据并刷新

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  2. Linux命令学习-sed

    sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为:         sed ...

  3. 14Mybatis_输入映射(传递pojo的包装对象)——很重要

    假设我们有这么一个需求:用户信息的综合查询,需要传入的查询条件很复杂(可能包括用户信息,其他的信息,比如商品,订单) 我们的思想是:传入到select中的parameterType是一个包装类,里面可 ...

  4. C# 利用BarcodeLib.dll生成条形码(一维,zxing,QrCodeNet/dll二维码)

    原文:http://blog.csdn.net/kongwei521/article/details/17588825 首先效果: 一.下载BarcodeLib.dll 下载地址 :http://do ...

  5. android中scrollTo和scrollBy的理解

    protected   int  mScrollX;    //该视图内容相当于视图起始坐标的偏移量   , X轴 方向 protected   int  mScrollY;    //该视图内容相当 ...

  6. Linux Shell编程二

    以"``"符号包含的内容不是字符串,而是代表这是一个shell命令. echo "today is" `date` 前面是字符,后面`date`表示执行date ...

  7. Qt——正则表达式

    在项目中经常会遇到对字符串进行操作的情况,我们可以直接使用QString的一些函数,但QT提供了一个更加强大的类——QRegExp,使用正则表达式来操作字符串. 先说说我最近遇到的几个问题: 1.对输 ...

  8. Google java代码风格导入Eclipse

    Git地址 https://github.com/codeset/google-java-styleguide 下载配置文件在Eclipse中执行导入:Window -> Preferences ...

  9. [CareerCup] 10.3 Integer not Contain in the File 文件中不包含的数

    10.3 Given an input file with four billion non-negative integers, provide an algorithm to generate a ...

  10. 20145316GDB调试汇编堆栈

    GDB调试例子的汇编堆栈 代码 直接-m32编译出现问题 编译64位Linux版本32位的二进制文件,需要安装一个库,使用指令sudo apt-get install libc6-dev-i386 编 ...